jiangqs
2023-08-06 beeda8df0023376dbb2021148a021731dc4aedb0
Merge branch 'master' of ssh://sinata.cn:20202/java/HongRuiTang into master

# Conflicts:
# ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/order/OrderService.java
# ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/impl/shop/ShopServiceImpl.java
# ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/WechatPayUtils.java
32个文件已修改
1个文件已删除
12个文件已添加
2298 ■■■■ 已修改文件
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/dto/AppBaseDto.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/ShopProportionVo.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteShopFallbackFactory.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/service/RemoteShopService.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SecurityUtils.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/config/MyWxPayConfig.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/config/WxPayConfiguration.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/config/WxPayProperties.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/AppOrderController.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/BackMessage.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderPayment.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderRefund.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/PaymentMessage.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/ProfitSharing.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/vo/AppPlaceOrderVo.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/vo/ProfitSharingNotifyNewResult.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/RefundStatusEnum.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/WxPayNotifyEventTypeEnum.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/dict/DictBean.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/dict/IDict.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/BackMessageService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/OrderPaymentService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/PaymentMessageService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/ProfitSharingService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/BackMessageServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/OrderPaymentServiceImpl.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/PaymentMessageServiceImpl.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/ProfitSharingServiceImpl.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java 821 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/order/OrderService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/resources/bootstrap.yml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/controller/console/ShopController.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/enums/WxApplyMentSignStateEnum.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/enums/WxApplyMentStateEnum.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/enums/dict/DictBean.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/enums/dict/IDict.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/scheduler/ShopScheduler.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/impl/shop/ShopAuthenticationServiceImpl.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/impl/shop/ShopProportionServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/impl/shop/ShopServiceImpl.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/shop/ShopAuthenticationService.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/shop/ShopProportionService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/shop/ShopService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/WechatPayUtils.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/dto/AppBaseDto.java
@@ -13,7 +13,12 @@
@Data
public class AppBaseDto {
    @ApiModelProperty(value = "userId",hidden = true)
    @ApiModelProperty(value = "userId", hidden = true)
    private Long userId;
    @ApiModelProperty(value = "openid", hidden = true)
    private String openid;
    @ApiModelProperty(value = "终端IP", hidden = true)
    private String spbillCreateIp;
}
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/ShopProportionVo.java
New file
@@ -0,0 +1,31 @@
package com.ruoyi.system.api.domain.poji.shop;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class ShopProportionVo {
    /**
     * 分成id
     */
    private Long proportionId;
    /**
     * 商户id
     */
    private Long shopId;
    /**
     * 商户类型
     */
    private Integer shopType;
    /**
     * 分成比例
     */
    private BigDecimal proportionPercent;
}
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteShopFallbackFactory.java
@@ -2,6 +2,7 @@
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.domain.dto.*;
import com.ruoyi.system.api.domain.poji.shop.ShopProportionVo;
import com.ruoyi.system.api.domain.vo.*;
import com.ruoyi.system.api.model.QwH5LoginVo;
import com.ruoyi.system.api.model.QwUserDetailDto;
@@ -33,6 +34,11 @@
            @Override
            public R<Shop> getShop(Long shopId) {
                return R.fail("获取商户失败:" + throwable.getMessage());
            }
            @Override
            public R<String> getShopSubMchId(Long shopId) {
                return R.fail("获取微信商户号失败:" + throwable.getMessage());
            }
            @Override
@@ -109,6 +115,11 @@
            public R editMgtShopStaff(MgtShopStaffEditDto mgtShopStaffEditDto) {
                return R.fail("修改员工失败:" + throwable.getMessage());
            }
            @Override
            public R<ShopProportionVo> getShopProportion(Long shopId) {
                return R.fail("获取商户分成信息失败:" + throwable.getMessage());
            }
        };
    }
}
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/service/RemoteShopService.java
@@ -4,6 +4,7 @@
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.domain.dto.*;
import com.ruoyi.system.api.domain.poji.shop.Shop;
import com.ruoyi.system.api.domain.poji.shop.ShopProportionVo;
import com.ruoyi.system.api.domain.vo.*;
import com.ruoyi.system.api.factory.RemoteShopFallbackFactory;
import com.ruoyi.system.api.model.QwH5LoginVo;
@@ -19,6 +20,10 @@
    @PostMapping("/shop/getShop")
    public R<Shop> getShop(@RequestBody Long shopId);
    @PostMapping("/shop/getShopSubMchId")
    public R<String> getShopSubMchId(@RequestBody Long shopId);
    @PostMapping("/shop/getShopByUserId")
    public R<ShopRelUserVo> getShopByUserId(@RequestBody Long userId);
@@ -149,4 +154,12 @@
     */
    @PostMapping("/shop/editMgtShopStaff")
    public R editMgtShopStaff(@RequestBody MgtShopStaffEditDto mgtShopStaffEditDto);
    /**
     * 获取商户分成
     * @param shopId
     * @return
     */
    @PostMapping("/shop/getShopProportion")
    R<ShopProportionVo> getShopProportion(@RequestBody Long shopId);
}
ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SecurityUtils.java
@@ -1,6 +1,8 @@
package com.ruoyi.common.security.utils;
import javax.servlet.http.HttpServletRequest;
import com.ruoyi.system.api.domain.poji.sys.SysUser;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.TokenConstants;
@@ -11,7 +13,7 @@
/**
 * 权限获取工具类
 *
 *
 * @author jqs
 */
public class SecurityUtils
@@ -48,6 +50,11 @@
        return SecurityContextHolder.get(SecurityConstants.LOGIN_USER, LoginUser.class);
    }
    public static SysUser getSysUser()
    {
        return getLoginUser().getSysUser();
    }
    /**
     * 获取请求token
     */
@@ -81,7 +88,7 @@
    /**
     * 是否为管理员
     *
     *
     * @param userId 用户ID
     * @return 结果
     */
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/config/MyWxPayConfig.java
File was deleted
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/config/WxPayConfiguration.java
New file
@@ -0,0 +1,54 @@
package com.ruoyi.order.config;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @author Binary Wang
 */
@Configuration
@ConditionalOnClass(WxPayService.class)
@EnableConfigurationProperties(WxPayProperties.class)
@AllArgsConstructor
public class WxPayConfiguration {
  private WxPayProperties properties;
  // 分账特约商户
  private static String PLATFORM_TY_MAC_ID = "";
  public static String getPlatformTyMacId() {
    return PLATFORM_TY_MAC_ID;
  }
  @Bean
  @ConditionalOnMissingBean
  public WxPayService wxService() {
    WxPayConfig payConfig = new WxPayConfig();
    payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
    payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
    payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
    payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
    payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
    payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
    // 平台特约商户号
    PLATFORM_TY_MAC_ID = this.properties.getPlatformTyMacId();
    // 可以指定是否使用沙箱环境
    payConfig.setUseSandboxEnv(false);
    WxPayService wxPayService = new WxPayServiceImpl();
    wxPayService.setConfig(payConfig);
    return wxPayService;
  }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/config/WxPayProperties.java
New file
@@ -0,0 +1,49 @@
package com.ruoyi.order.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
 * wxpay pay properties.
 *
 * @author Binary Wang
 */
@Data
@ConfigurationProperties(prefix = "wx.pay")
public class WxPayProperties {
  /**
   * 设置微信公众号或者小程序等的appid
   */
  private String appId;
  /**
   * 微信支付商户号
   */
  private String mchId;
  /**
   * 微信支付商户密钥
   */
  private String mchKey;
  /**
   * 平台特约商户号,用户平台收取服务费
   */
  private String platformTyMacId;
  /**
   * 服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除
   */
  private String subAppId;
  /**
   * 服务商模式下的子商户号,普通模式请不要配置,最好是请在配置文件中将对应项删除
   */
  private String subMchId;
  /**
   * apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定
   */
  private String keyPath;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/AppOrderController.java
@@ -15,6 +15,7 @@
import com.ruoyi.system.api.domain.dto.AppBaseGetDto;
import com.ruoyi.system.api.domain.dto.AppMemberBindingDto;
import com.ruoyi.system.api.domain.poji.member.Member;
import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.system.api.service.RemoteConfigService;
import com.ruoyi.system.api.service.RemoteMemberService;
import io.swagger.annotations.Api;
@@ -57,10 +58,10 @@
    @ApiOperation(value = "购买商品")
    public R<AppSureOrderVo> buyGoods(@RequestBody AppSureOrderDto appSureOrderDto) {
        Long userId = SecurityUtils.getUserId();
        if(userId!=null){
        if (userId != null) {
            Member member = memberService.getMember(userId).getData();
            appSureOrderDto.setUserId(userId);
            if(member!=null&&member.getRelationShopId()!=null){
            if (member != null && member.getRelationShopId() != null) {
                appSureOrderDto.setShopId(member.getRelationShopId());
            }
        }
@@ -73,10 +74,10 @@
    @ApiOperation(value = "抢购商品")
    public R<AppPanicBuyVo> panicBuyGoods(@RequestBody AppPanicBuyDto appPanicBuyDto) {
        Long userId = SecurityUtils.getUserId();
        if(userId!=null){
        if (userId != null) {
            Member member = memberService.getMember(userId).getData();
            appPanicBuyDto.setUserId(userId);
            if(member!=null&&member.getRelationShopId()!=null){
            if (member != null && member.getRelationShopId() != null) {
                appPanicBuyDto.setShopId(member.getRelationShopId());
            }
        }
@@ -87,20 +88,26 @@
    @RequestMapping(value = "/placeOrder", method = RequestMethod.POST)
    @ApiOperation(value = "创建订单")
    public R<AppPlaceOrderVo> placeOrder(@RequestBody AppPlaceOrderDto appPlaceOrderDto) {
        Long userId = SecurityUtils.getUserId();
        if(userId!=null){
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long userId = loginUser.getUserid();
        appPlaceOrderDto.setUserId(userId);
        appPlaceOrderDto.setSpbillCreateIp(loginUser.getIpaddr());
        if (userId != null) {
            Member member = memberService.getMember(userId).getData();
            appPlaceOrderDto.setUserId(userId);
            if(member!=null&&member.getRelationShopId()!=null){
            if (member != null) {
                appPlaceOrderDto.setOpenid(member.getMiniOpenid());
                appPlaceOrderDto.setShopId(member.getRelationShopId());
            }
            if(member.getBindingFlag()!=1){
                //绑定商户
                AppMemberBindingDto appMemberBindingDto = new AppMemberBindingDto();
                appMemberBindingDto.setShopId(appPlaceOrderDto.getShopId());
                appMemberBindingDto.setUserId(userId);
                appMemberBindingDto.setBindingFlag(1);
                memberService.updateMemberBinding(appMemberBindingDto);
                if (member.getBindingFlag() != 1) {
                    //绑定商户
                    AppMemberBindingDto appMemberBindingDto = new AppMemberBindingDto();
                    appMemberBindingDto.setShopId(appPlaceOrderDto.getShopId());
                    appMemberBindingDto.setUserId(userId);
                    appMemberBindingDto.setBindingFlag(1);
                    memberService.updateMemberBinding(appMemberBindingDto);
                }
            }
        }
        AppPlaceOrderVo appPlaceOrderVo = orderService.placeOrder(appPlaceOrderDto);
@@ -111,13 +118,13 @@
    @ApiOperation(value = "创建活动订单")
    public R<AppPlaceOrderVo> placeActivityOrder(@Validated @RequestBody AppPlaceActivityDto appPlaceActivityDto) {
        Long userId = SecurityUtils.getUserId();
        if(userId!=null){
        if (userId != null) {
            Member member = memberService.getMember(userId).getData();
            appPlaceActivityDto.setUserId(userId);
            if(member!=null&&member.getRelationShopId()!=null){
            if (member != null && member.getRelationShopId() != null) {
                appPlaceActivityDto.setShopId(member.getRelationShopId());
            }
            if(member.getBindingFlag()!=1){
            if (member.getBindingFlag() != 1) {
                //绑定商户
                AppMemberBindingDto appMemberBindingDto = new AppMemberBindingDto();
                appMemberBindingDto.setShopId(appPlaceActivityDto.getShopId());
@@ -134,18 +141,18 @@
    @ApiOperation(value = "分页获取用户订单")
    public R<Page<AppUserOrderPageVo>> pageUserOrder(@RequestBody AppUserOrderPageDto appUserOrderPageDto) {
        Long userId = SecurityUtils.getUserId();
        if(userId!=null){
        if (userId != null) {
            Member member = memberService.getMember(userId).getData();
            appUserOrderPageDto.setUserId(userId);
            if(member!=null&&member.getRelationShopId()!=null){
            if (member != null && member.getRelationShopId() != null) {
                appUserOrderPageDto.setShopId(member.getRelationShopId());
            }
        }
        logger.info("appUserOrderPageDto:"+appUserOrderPageDto.toString());
        logger.info("appUserOrderPageDto:" + appUserOrderPageDto.toString());
        Page<AppUserOrderPageVo> page = new Page<>();
        page.setSize(appUserOrderPageDto.getPageSize());
        page.setCurrent(appUserOrderPageDto.getPageNum());
        List<AppUserOrderPageVo> appUserOrderPageVoList = orderService.pageUserOrder(page,appUserOrderPageDto);
        List<AppUserOrderPageVo> appUserOrderPageVoList = orderService.pageUserOrder(page, appUserOrderPageDto);
        return R.ok(page.setRecords(appUserOrderPageVoList));
    }
@@ -154,17 +161,17 @@
    public R<AppUserOrderGetVo> getAppOrderDetail(@RequestBody AppBaseGetDto appBaseGetDto) {
        Long userId = SecurityUtils.getUserId();
        Long shopId = null;
        if(userId!=null){
        if (userId != null) {
            Member member = memberService.getMember(userId).getData();
            appBaseGetDto.setUserId(userId);
            if(member!=null&&member.getRelationShopId()!=null){
            if (member != null && member.getRelationShopId() != null) {
                shopId = member.getRelationShopId();
            }
        }
        AppUserOrderGetVo appUserOrderGetVo = orderService.getAppOrderDetail(appBaseGetDto);
        if(shopId!=null&&appUserOrderGetVo.getShopId().equals(shopId)){
        if (shopId != null && appUserOrderGetVo.getShopId().equals(shopId)) {
            appUserOrderGetVo.setSameShop(1);
        }else{
        } else {
            appUserOrderGetVo.setSameShop(0);
        }
        return R.ok(appUserOrderGetVo);
@@ -184,12 +191,12 @@
        appPlaceOrderVo.setPayMoney(order.getPayMoney());
        appPlaceOrderVo.setUnpaidMoney(order.getPayMoney());
        Integer delayTime = 30;
        if(redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)){
        if (redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)) {
            delayTime = redisService.getCacheObject(SecurityConstant.AUTO_CANCEL_ORDER_TIME);
        }
        redisService.deleteObject(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + order.getOrderId());
        remoteConfigService.deleteDelayTask(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + order.getOrderId());
        appPlaceOrderVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(),delayTime));
        appPlaceOrderVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(), delayTime));
        return R.ok(appPlaceOrderVo);
    }
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java
@@ -1,38 +1,34 @@
package com.ruoyi.order.controller.miniapp;
import com.ruoyi.common.core.domain.R;
import com.github.binarywang.wxpay.bean.ecommerce.*;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Response;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyData;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.ProfitSharingV3Service;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.v3.auth.Verifier;
import com.github.binarywang.wxpay.v3.util.AesUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.order.domain.dto.AppSureOrderDto;
import com.ruoyi.order.domain.dto.WXPayNotifyDto;
import com.ruoyi.order.domain.vo.AppSureOrderVo;
import com.ruoyi.order.domain.vo.ProfitSharingNotifyNewResult;
import com.ruoyi.order.enums.WxPayNotifyEventTypeEnum;
import com.ruoyi.order.service.account.BackMessageService;
import com.ruoyi.order.service.order.OrderService;
import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.RSAConfig;
import com.wechat.pay.java.core.cipher.PrivacyEncryptor;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.bytebuddy.asm.Advice;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.security.GeneralSecurityException;
import java.util.Map;
import java.util.Objects;
/**
 * @program: ruoyi
@@ -44,88 +40,82 @@
@RestController
@RequestMapping("/app/notify")
public class NotifyController extends BaseController {
    /** 商户号 */
    public static String merchantId = "";
    /** 商户API私钥路径 */
    public static String privateKeyPath = "";
    /** 商户证书序列号 */
    public static String merchantSerialNumber = "";
    /** 微信支付平台证书路径 */
    public static String wechatPayCertificatePath = "";
    /** 商户APIV3密钥 */
    public static String apiV3key = "...";
    public static final String WECHAT_PAY_SERIAL = "Wechatpay-Serial";
    public static final String WECHAT_PAY_SIGNATURE = "Wechatpay-Signature";
    public static final String WECHAT_PAY_TIMESTAMP = "Wechatpay-Timestamp";
    public static final String WECHAT_PAY_NONCE = "Wechatpay-Nonce";
    private static final Gson GSON = new GsonBuilder().create();
    @Resource
    private OrderService orderService;
    @RequestMapping(value = "/payNotify", method = RequestMethod.POST)
    @ApiOperation(value = "微信支付通知")
    public Map payNotify(HttpServletRequest request, HttpServletResponse response) {
        Config config =
                new RSAConfig.Builder()
                        .merchantId(merchantId)
                        .privateKeyFromPath(privateKeyPath)
                        .merchantSerialNumber(merchantSerialNumber)
                        .wechatPayCertificatesFromPath(wechatPayCertificatePath)
                        .build();
    @Autowired
    private WxPayService wxService;
    @Resource
    private BackMessageService backMessageService;
        PrivacyEncryptor encryptor = config.createEncryptor();
        String wechatPayCertificateSerialNumber = encryptor.getWechatpaySerial();
    @PostMapping(value = "/payNotify")
    @ApiOperation(value = "微信支付/退款通知")
    public String payNotify(@RequestBody String notifyData, HttpServletRequest request, HttpServletResponse response) throws WxPayException {
        // 获取请求头
        SignatureHeader signatureHeader = getSignatureHeader(response);
        String nonoc=request.getHeader("Wechatpay-Nonce");
        String signature=request.getHeader("Wechatpay-Signature");
        String timestamp=request.getHeader("Wechatpay-Timestamp");
        String serial=request.getHeader("Wechatpay-Serial");
        String signatureType=request.getHeader("Wechatpay-Signature-Type");
        NotifyResponse responseData = GSON.fromJson(notifyData, NotifyResponse.class);
        String eventType = responseData.getEventType();
        String requestBody="";
        try {
            BufferedReader reader = request.getReader();
            String line = "";
            StringBuffer inputString = new StringBuffer();
            while ( (line = reader.readLine()) != null ) {
                inputString.append(line);
        int resultType = 1;
        String resultMessage = "";
        if(WxPayNotifyEventTypeEnum.TRANSACTION_SUCCESS.getCode().equals(eventType)){
            PartnerTransactionsNotifyResult notifyResult = wxService.getEcommerceService().parsePartnerNotifyResult(notifyData, signatureHeader);
            PartnerTransactionsResult result = notifyResult.getResult();
            // 支付通知回调
            if("SUCCESS".equals(result.getTradeState())){
                orderService.payBack(result);
            }
            if(inputString!=null && !"".equals(inputString)) {
                requestBody = inputString.toString();
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
            resultMessage = GSON.toJson(notifyResult);
        } else if(WxPayNotifyEventTypeEnum.REFUND_SUCCESS.getCode().equals(eventType)
            || WxPayNotifyEventTypeEnum.REFUND_ABNORMAL.getCode().equals(eventType)
            || WxPayNotifyEventTypeEnum.REFUND_CLOSED.getCode().equals(eventType)){
            RefundNotifyResult result = wxService.getEcommerceService().parseRefundNotifyResult(notifyData, signatureHeader);
            orderService.orderRefundBack(result);
            resultType = 2;
            resultMessage = GSON.toJson(result);
        }
        // 保存支付/退款回调信息
        backMessageService.saveBackMessage(resultType, resultMessage);
        return WxPayNotifyV3Response.success("成功");
    }
    @PostMapping(value = "/profitSharingNotify")
    @ApiOperation(value = "微信分账通知")
    public String profitSharingNotify(@RequestBody String notifyData, HttpServletRequest request, HttpServletResponse response) throws WxPayException {
        ProfitSharingV3Service sharingV3Service = wxService.getProfitSharingV3Service();
        // ProfitSharingNotifyResult
        // 获取请求头
        SignatureHeader signatureHeader = getSignatureHeader(response);
        ProfitSharingNotifyNewResult notifyResult = getProfitSharingNotifyData(notifyData, signatureHeader);
        ProfitSharingNotifyResult result = notifyResult.getResult();
        String eventType = notifyResult.getRawData().getEventType();
        if(WxPayNotifyEventTypeEnum.PROFIT_SHARING_SUCCESS.getCode().equals(eventType)){
            // 分账通知回调
            orderService.profitSharingBack(result);
        }
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatPayCertificateSerialNumber)
                .nonce(nonoc)
                .signature(signature)
                .timestamp(timestamp)
                .body(requestBody)
                .build();
        String resultMessage = GSON.toJson(notifyResult);
        // 保存记录分账回调信息
        backMessageService.saveBackMessage(3, resultMessage);
        NotificationConfig notifiConfig = new RSAAutoCertificateConfig.Builder()
                .merchantId(merchantId)
                .privateKeyFromPath(privateKeyPath)
                .merchantSerialNumber(merchantSerialNumber)
                .apiV3Key(apiV3key)
                .build();
        NotificationParser parser = new NotificationParser(notifiConfig);
        Transaction transaction = parser.parse(requestParam, Transaction.class);
        String tradeStateEnum=transaction.getTradeState().toString();
        if(tradeStateEnum.equals("success")){
            orderService.payBack(transaction);
        }
        Map map=new HashMap();
        map.put("code","SUCCESS");
        map.put("message","成功");
        return map;
        return WxPayNotifyV3Response.success("成功");
    }
    @RequestMapping(value = "/shareNotify", method = RequestMethod.POST)
@@ -135,4 +125,49 @@
        return null;
    }
    public ProfitSharingNotifyNewResult getProfitSharingNotifyData(String notifyData, SignatureHeader header) throws WxPayException {
        if (Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)) {
            throw new WxPayException("非法请求,头部信息验证失败");
        }
        ProfitSharingNotifyData response = GSON.fromJson(notifyData, ProfitSharingNotifyData.class);
        ProfitSharingNotifyData.Resource resource = response.getResource();
        String cipherText = resource.getCipherText();
        String associatedData = resource.getAssociatedData();
        String nonce = resource.getNonce();
        String apiV3Key = this.wxService.getConfig().getApiV3Key();
        try {
            String result = AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key);
            ProfitSharingNotifyResult profitSharingResult = GSON.fromJson(result, ProfitSharingNotifyResult.class);
            ProfitSharingNotifyNewResult notifyResult = new ProfitSharingNotifyNewResult();
            notifyResult.setRawData(response);
            notifyResult.setResult(profitSharingResult);
            return notifyResult;
        } catch (GeneralSecurityException | IOException e) {
            throw new WxPayException("解析报文异常!", e);
        }
    }
    private boolean verifyNotifySign(SignatureHeader header, String data) throws WxPayException {
        String beforeSign = String.format("%s\n%s\n%s\n",
                header.getTimeStamp(),
                header.getNonce(),
                data);
        Verifier verifier = this.wxService.getConfig().getVerifier();
        if (verifier == null) {
            throw new WxPayException("证书检验对象为空");
        }
        return verifier.verify(header.getSerialNo(),
                beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned());
    }
    private SignatureHeader getSignatureHeader(HttpServletResponse response){
        SignatureHeader signatureHeader = new SignatureHeader();
        signatureHeader.setSerialNo(response.getHeader(WECHAT_PAY_SERIAL));
        signatureHeader.setSigned(response.getHeader(WECHAT_PAY_SIGNATURE));
        signatureHeader.setNonce(response.getHeader(WECHAT_PAY_NONCE));
        signatureHeader.setTimeStamp(response.getHeader(WECHAT_PAY_TIMESTAMP));
        return signatureHeader;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/BackMessage.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -38,7 +39,7 @@
    @TableField("del_flag")
    private String delFlag;
    /**
     * 回调类型1支付回调2退款回调
     * 回调类型 1支付回调 2退款回调 3、分账
     */
    @TableField("result_type")
    private Integer resultType;
@@ -47,6 +48,11 @@
     */
    @TableField("result_message")
    private String resultMessage;
    /**
     * 回调时间
     */
    @TableField("create_time")
    private Date createTime;
    @Override
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderPayment.java
@@ -49,6 +49,12 @@
    @TableField("shop_id")
    private Long shopId;
    /**
     * 订单二级商户号
     */
    @TableField("sub_mch_id")
    private String subMchId;
    /**
     * 订单id
     */
    @TableField("order_id")
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderRefund.java
@@ -99,7 +99,21 @@
     * 回调时间
     */
    @TableField("back_time")
    private Date backTime;
    private String backTime;
    /**
     * 微信退款订单id
     */
    @TableField("wx_refund_id")
    private String wxRefundId;
    /**
     * 1、发起退款 2、已退款
     */
    @TableField("refund_status")
    private Integer refundStatus;
    @Override
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/PaymentMessage.java
@@ -47,7 +47,7 @@
     * 发起关联id
     */
    @TableField("send_id")
    private Long sendId;
    private String sendId;
    /**
     * 发送报文
     */
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/ProfitSharing.java
@@ -40,7 +40,7 @@
    private Integer delFlag;
    /**
     * 1:PROCESSING:处理中
2:FINISHED:分账完成
        2:FINISHED:分账完成
     */
    @TableField("share_status")
    private Integer shareStatus;
@@ -93,7 +93,15 @@
     * 完成时间
     */
    @TableField("finish_time")
    private Date finishTime;
    private String finishTime;
    /**
     * 微信分账/回退单号
     */
    @TableField("wx_order_id")
    private String wxOrderId;
    /**
     * 分账失败原因
1、ACCOUNT_ABNORMAL : 分账接收账户异常
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/vo/AppPlaceOrderVo.java
@@ -54,7 +54,7 @@
    private String packageStr;
    @ApiModelProperty(value = "签名方式")
    private String tradeType;
    private String signType;
    @ApiModelProperty(value = "签名")
    private String paySign;
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/vo/ProfitSharingNotifyNewResult.java
New file
@@ -0,0 +1,23 @@
package com.ruoyi.order.domain.vo;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyData;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyResult;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
public class ProfitSharingNotifyNewResult implements Serializable {
    private static final long serialVersionUID = -6602962275015706689L;
    /**
     * 源数据
     */
    private ProfitSharingNotifyData rawData;
    /**
     * 解密后的数据
     */
    private ProfitSharingNotifyResult result;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/RefundStatusEnum.java
New file
@@ -0,0 +1,19 @@
package com.ruoyi.order.enums;
import com.ruoyi.order.enums.dict.IDict;
public enum RefundStatusEnum implements IDict<Integer> {
    /**
     * 退款状态,枚举值:
     * SUCCESS:退款成功
     * CLOSE:退款关闭
     * ABNORMAL:退款异常
     */
    SUCCESS(2, "SUCCESS"),
    CLOSE(3, "CLOSE"),
    ABNORMAL(4, "ABNORMAL");
    RefundStatusEnum(Integer code, String text){
        init(code, text);
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/WxPayNotifyEventTypeEnum.java
New file
@@ -0,0 +1,22 @@
package com.ruoyi.order.enums;
import com.ruoyi.order.enums.dict.IDict;
public enum WxPayNotifyEventTypeEnum implements IDict<String> {
    /**
     * 微信回调通知
        支付成功通知的类型为 TRANSACTION.SUCCESS
        分账 PROFITSHARING.SUCCESS
     */
    TRANSACTION_SUCCESS("TRANSACTION.SUCCESS", "TRANSACTION.SUCCESS"),
    PROFIT_SHARING_SUCCESS("PROFITSHARING.SUCCESS", "PROFITSHARING.SUCCESS"),
    REFUND_SUCCESS("REFUND.SUCCESS", "REFUND.SUCCESS"),
    REFUND_ABNORMAL("REFUND.ABNORMAL", "REFUND.ABNORMAL"),
    REFUND_CLOSED("REFUND.CLOSED", "REFUND.CLOSED");
    WxPayNotifyEventTypeEnum(String code, String text){
        init(code, text);
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/dict/DictBean.java
New file
@@ -0,0 +1,15 @@
package com.ruoyi.order.enums.dict;
import lombok.Data;
/**
 * 字典bean
 * 只有code和text,可用于展示下拉框
 *
 * @author luozhan
 */
@Data
public class DictBean<T> implements IDict<T> {
    private final T code;
    private final String text;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/dict/IDict.java
New file
@@ -0,0 +1,170 @@
package com.ruoyi.order.enums.dict;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
 * 字典接口
 * <p>
 * 自定义的字典枚举类实现本接口后可省略属性code和text,以及对应的get方法
 * 在构造方法中只需调用init方法即可初始化
 *
 * @author luozhan
 * @date 2021-12
 */
public interface IDict<T> {
    /**
     * 通过code获取value
     *
     * @param clazz 枚举class
     * @param code  code
     * @return text
     */
    static <T> String getTextByCode(Class<? extends IDict<T>> clazz, T code) {
        return Stream.of(clazz.getEnumConstants())
                .filter((IDict<T> e) -> e.getCode().equals(code))
                .map(IDict::getText)
                .findAny().orElse("");
    }
    /**
     * 通过text获取code
     *
     * @param clazz 枚举class
     * @param text  text
     * @return code
     */
    static <T> T getCodeByText(Class<? extends IDict<T>> clazz, String text) {
        return Stream.of(clazz.getEnumConstants())
                .filter((IDict<T> e) -> e.getText().equals(text))
                .map(IDict::getCode)
                .findAny().orElse(null);
    }
    /**
     * 通过code获取字典枚举实例
     *
     * @param clazz 枚举class
     * @param code  code
     * @param <T>   字典code类型
     * @param <R>   枚举类型
     * @return 字典枚举实例
     */
    @SuppressWarnings("unchecked")
    static <T, R extends IDict<T>> R getByCode(Class<? extends IDict<T>> clazz, T code) {
        return Stream.of(clazz.getEnumConstants())
                .filter((IDict<T> e) -> (e.getCode().equals(code)))
                .map(v -> (R) v)
                .findAny()
                .orElse(null);
    }
    /**
     * 获取给定的字典枚举项(常用下拉框数据请求)
     *
     * @param enums 可指定需要哪些项
     * @return List
     */
    @SafeVarargs
    static <T, E extends IDict<T>> List<IDict<T>> getItems(E... enums) {
        return Stream.of(enums)
                .map(DictPool::getDict)
                .collect(Collectors.toList());
    }
    /**
     * 获取所有字典枚举项,除开指定的枚举
     *
     * @param exclude 指定排除的枚举
     * @return List
     */
    @SafeVarargs
    @SuppressWarnings("unchecked")
    static <T, E extends IDict<T>> List<IDict<T>> getItemsExclude(E... exclude) {
        Class<IDict<T>> clazz = (Class<IDict<T>>) exclude.getClass().getComponentType();
        IDict<T>[] allEnum = clazz.getEnumConstants();
        List<IDict<T>> excludeList = Arrays.asList(exclude);
        return Stream.of(allEnum)
                .filter(e -> !excludeList.contains(e))
                .map(DictPool::getDict)
                .collect(Collectors.toList());
    }
    /**
     * 获取所有字典枚举项(常用下拉框数据请求)
     * 枚举值上标记@Deprecated的不会返回
     *
     * @param clazz 字典枚举类
     * @return List
     */
    static <T> List<IDict<T>> getAll(Class<? extends IDict<T>> clazz) {
        Map<String, Field> fieldCache = Arrays.stream(clazz.getDeclaredFields()).
                filter(Field::isEnumConstant).
                collect(Collectors.toMap(Field::getName, Function.identity()));
        IDict<T>[] allEnum = clazz.getEnumConstants();
        return Stream.of(allEnum)
                .filter(e -> !fieldCache.get(((Enum<?>) e).name()).isAnnotationPresent(Deprecated.class))
                .map(DictPool::getDict)
                .collect(Collectors.toList());
    }
    /**
     * 初始化
     *
     * @param code 字典编码
     * @param text 字典文本
     */
    default void init(T code, String text) {
        DictPool.putDict(this, code, text);
    }
    /**
     * 获取编码
     *
     * @return 编码
     */
    default T getCode() {
        return DictPool.getDict(this).getCode();
    }
    /**
     * 获取文本
     *
     * @return 文本
     */
    default String getText() {
        return DictPool.getDict(this).getText();
    }
    @SuppressWarnings("all")
    class DictPool {
        private static final Map<IDict, DictBean> DICT_MAP = new ConcurrentHashMap<>();
        private static final Map<String, Class<? extends IDict>> DICT_NAME_CLASS_MAP = new ConcurrentHashMap<>();
        static <T> void putDict(IDict<T> dict, T code, String text) {
            DICT_NAME_CLASS_MAP.put(dict.getClass().getName(), dict.getClass());
            DICT_MAP.put(dict, new DictBean<>(code, text));
        }
        public static List<IDict<Object>> getDict(String dictName) {
            Class<? extends IDict> aClass = DICT_NAME_CLASS_MAP.get(dictName);
            return IDict.getAll((Class<? extends IDict<Object>>) aClass);
        }
        static <K extends IDict<T>, T> DictBean<T> getDict(K dict) {
            return DICT_MAP.get(dict);
        }
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/BackMessageService.java
@@ -13,4 +13,10 @@
 */
public interface BackMessageService extends IService<BackMessage> {
    /**
     * 保存回调记录
     * @param resultType
     * @param resultMessage
     */
    void saveBackMessage(int resultType, String resultMessage);
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/OrderPaymentService.java
@@ -3,6 +3,9 @@
import com.ruoyi.order.domain.pojo.account.OrderPayment;
import com.baomidou.mybatisplus.extension.service.IService;
import java.math.BigDecimal;
import java.util.Date;
/**
 * <p>
 * 订单支付 服务类
@@ -13,4 +16,24 @@
 */
public interface OrderPaymentService extends IService<OrderPayment> {
    /**
     * 保存支付记录
     * @param userId
     * @param shopId
     * @param orderId
     * @param payMoney
     * @param endTime
     * @param profitSharing
     * @param openid
     * @param goodsNames
     * @param prepayId
     */
    void saveOrderPayment(Long userId, Long shopId, String subMchId, String orderId, BigDecimal payMoney, Date endTime, String profitSharing, String openid, String goodsNames, String prepayId);
    /**
     *
     * @param orderId
     * @return
     */
    OrderPayment getByOrderId(String orderId);
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/PaymentMessageService.java
@@ -13,4 +13,12 @@
 */
public interface PaymentMessageService extends IService<PaymentMessage> {
    /**
     * 保存请求信息
     * @param sendType
     * @param sendId
     * @param sendMessage
     * @param resultMessage
     */
    void savePaymentMessage(String sendType, String sendId, String sendMessage, String resultMessage);
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/ProfitSharingService.java
@@ -1,7 +1,10 @@
package com.ruoyi.order.service.account;
import com.github.binarywang.wxpay.bean.ecommerce.ProfitSharingResult;
import com.ruoyi.order.domain.pojo.account.ProfitSharing;
import com.baomidou.mybatisplus.extension.service.IService;
import java.math.BigDecimal;
/**
 * <p>
@@ -13,4 +16,12 @@
 */
public interface ProfitSharingService extends IService<ProfitSharing> {
    /**
     * 创建按分账记录
     * @param shopId
     * @param orderId
     * @param orderMoney
     * @param result
     */
    void saveProfitSharing(Long shopId, String orderId, BigDecimal orderMoney, ProfitSharingResult result);
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/BackMessageServiceImpl.java
@@ -6,6 +6,8 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.Date;
/**
 * <p>
 * 回调报文 服务实现类
@@ -17,4 +19,13 @@
@Service
public class BackMessageServiceImpl extends ServiceImpl<BackMessageMapper, BackMessage> implements BackMessageService {
    @Override
    public void saveBackMessage(int resultType, String resultMessage) {
        BackMessage backMessage = new BackMessage();
        backMessage.setDelFlag("0");
        backMessage.setResultType(resultType);
        backMessage.setResultMessage(resultMessage);
        backMessage.setCreateTime(new Date());
        this.saveOrUpdate(backMessage);
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/OrderPaymentServiceImpl.java
@@ -1,10 +1,16 @@
package com.ruoyi.order.service.impl.account;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.core.utils.uuid.IdUtils;
import com.ruoyi.order.domain.pojo.account.OrderPayment;
import com.ruoyi.order.mapper.account.OrderPaymentMapper;
import com.ruoyi.order.service.account.OrderPaymentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
/**
 * <p>
@@ -17,4 +23,34 @@
@Service
public class OrderPaymentServiceImpl extends ServiceImpl<OrderPaymentMapper, OrderPayment> implements OrderPaymentService {
    @Override
    public void saveOrderPayment(Long userId, Long shopId, String subMchId, String orderId, BigDecimal payMoney, Date endTime,
                                 String profitSharing, String openid, String goodsNames, String prepayId) {
        OrderPayment payment = new OrderPayment();
        payment.setPaymentId(IdUtils.simpleUUID());
        payment.setUserId(userId);
        payment.setShopId(shopId);
        payment.setOrderId(orderId);
        payment.setPayMoney(payMoney);
        payment.setTimeExpire(endTime);
        payment.setSubMchId(subMchId);
        // 0 否 1、是
        payment.setProfitSharing("Y".equals(profitSharing) ? 1 : 0);
        payment.setUserOpenId(openid);
        payment.setGoodsNames(goodsNames);
        payment.setPrepayId(prepayId);
        payment.setCreateTime(new Date());
        payment.setDelFlag(0);
        this.saveOrUpdate(payment);
    }
    @Override
    public OrderPayment getByOrderId(String orderId) {
        LambdaQueryWrapper<OrderPayment> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(OrderPayment::getOrderId, orderId)
                .eq(OrderPayment::getDelFlag, 0)
                .eq(OrderPayment::getPayStatus, 2)
                .last(" limit 1 ");
        return this.getOne(queryWrapper);
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/PaymentMessageServiceImpl.java
@@ -6,6 +6,8 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.Date;
/**
 * <p>
 * 支付报文 服务实现类
@@ -17,4 +19,15 @@
@Service
public class PaymentMessageServiceImpl extends ServiceImpl<PaymentMessageMapper, PaymentMessage> implements PaymentMessageService {
    @Override
    public void savePaymentMessage(String sendType, String sendId, String sendMessage, String resultMessage) {
        PaymentMessage paymentMessage = new PaymentMessage();
        paymentMessage.setDelFlag("0");
        paymentMessage.setSendType(sendType);
        paymentMessage.setSendId(sendId);
        paymentMessage.setSendMessage(sendMessage);
        paymentMessage.setResultMessage(resultMessage);
        paymentMessage.setCreateTime(new Date());
        this.saveOrUpdate(paymentMessage);
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/ProfitSharingServiceImpl.java
@@ -1,10 +1,17 @@
package com.ruoyi.order.service.impl.account;
import com.github.binarywang.wxpay.bean.ecommerce.ProfitSharingResult;
import com.ruoyi.common.core.utils.uuid.IdUtils;
import com.ruoyi.order.domain.pojo.account.ProfitSharing;
import com.ruoyi.order.mapper.account.ProfitSharingMapper;
import com.ruoyi.order.service.account.ProfitSharingService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
/**
 * <p>
@@ -17,4 +24,31 @@
@Service
public class ProfitSharingServiceImpl extends ServiceImpl<ProfitSharingMapper, ProfitSharing> implements ProfitSharingService {
    @Override
    public void saveProfitSharing(Long shopId, String orderId, BigDecimal orderMoney, ProfitSharingResult result) {
        ProfitSharing profitSharing = new ProfitSharing();
        profitSharing.setShareId(result.getOutOrderNo());
        profitSharing.setDelFlag(0);
        profitSharing.setShareStatus("FINISHED".equals(result.getStatus()) ? 2 : 1);
        profitSharing.setShopId(shopId);
        profitSharing.setOrderId(orderId);
        profitSharing.setOrderMoney(orderMoney);
        List<ProfitSharingResult.Receiver> receivers = result.getReceivers();
        if(null != receivers && !receivers.isEmpty()){
            ProfitSharingResult.Receiver receiver = receivers.get(0);
            profitSharing.setReceiverAccount(receiver.getReceiverMchid());
            BigDecimal receiverAmount = new BigDecimal(receiver.getAmount());
            receiverAmount = receiverAmount.divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
            profitSharing.setReceiverAmount(receiverAmount);
            profitSharing.setSurpMoney(orderMoney.subtract(receiverAmount));
            profitSharing.setReceiverDescription(receiver.getDescription());
            profitSharing.setFinishFlag(0);
            profitSharing.setFailReason(receiver.getFailReason());
            profitSharing.setDetailId(receiver.getDetailId());
        }
        profitSharing.setCreateTime(new Date());
        this.saveOrUpdate(profitSharing);
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java
@@ -1,10 +1,21 @@
package com.ruoyi.order.service.impl.order;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.ecommerce.*;
import com.github.binarywang.wxpay.bean.ecommerce.ProfitSharingRequest.Receiver;
import com.github.binarywang.wxpay.bean.ecommerce.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.common.base.Joiner;
import com.google.gson.Gson;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
@@ -12,15 +23,23 @@
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.utils.CodeFactoryUtil;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.order.config.WxPayConfiguration;
import com.ruoyi.order.domain.dto.*;
import com.ruoyi.order.domain.pojo.account.OrderPayment;
import com.ruoyi.order.domain.pojo.account.OrderRefund;
import com.ruoyi.order.domain.pojo.account.ProfitSharing;
import com.ruoyi.order.domain.pojo.order.ConsumerGoods;
import com.ruoyi.order.domain.pojo.order.Order;
import com.ruoyi.order.domain.pojo.order.OrderGoods;
import com.ruoyi.order.domain.pojo.order.PayRecord;
import com.ruoyi.order.domain.vo.*;
import com.ruoyi.order.enums.RefundStatusEnum;
import com.ruoyi.order.enums.dict.IDict;
import com.ruoyi.order.mapper.order.OrderMapper;
import com.ruoyi.order.service.account.OrderPaymentService;
import com.ruoyi.order.service.account.OrderRefundService;
import com.ruoyi.order.service.account.PaymentMessageService;
import com.ruoyi.order.service.account.ProfitSharingService;
import com.ruoyi.order.service.order.*;
import com.ruoyi.system.api.constant.AppErrorConstant;
import com.ruoyi.system.api.constant.DelayTaskEnum;
@@ -35,10 +54,11 @@
import com.ruoyi.system.api.domain.poji.member.MemberCoupon;
import com.ruoyi.system.api.domain.poji.member.MemberGiftRecord;
import com.ruoyi.system.api.domain.poji.shop.Shop;
import com.ruoyi.system.api.domain.poji.shop.ShopProportionVo;
import com.ruoyi.system.api.domain.poji.sys.SysUser;
import com.ruoyi.system.api.domain.vo.*;
import com.ruoyi.system.api.service.*;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
@@ -47,6 +67,7 @@
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
@@ -63,6 +84,7 @@
 * @since 2023-04-25
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    @Resource
@@ -110,22 +132,20 @@
    @Autowired
    private RedissonClient redissonClient;
    /** 商户号 */
    public static String merchantId = "";
    /** 商户API私钥路径 */
    public static String privateKeyPath = "";
    /** 商户证书序列号 */
    public static String merchantSerialNumber = "";
    /** 微信支付平台证书路径 */
    public static String wechatPayCertificatePath = "";
    /** 微信支付 APIv3 密钥 */
    public static String apiV3Key = "";
    /** 微信支付APPID */
    public static String appId="";
    /** 微信支付商户ID */
    public static String mchId="";
    /** 通知地址 */
    public static String notifyUrl="";
    @Autowired
    private WxPayService wxService;
    @Resource
    private PaymentMessageService paymentMessageService;
    @Resource
    private OrderPaymentService orderPaymentService;
    @Resource
    private ProfitSharingService profitSharingService;
    @Resource
    private OrderRefundService orderRefundService;
    /**
     * @description: buyGoods
@@ -153,8 +173,8 @@
        Map<String, Goods> goodsMap = goodsList.stream()
                .collect(Collectors.toMap(Goods::getGoodsId, Function.identity()));
        Boolean haveDeposit = false;
        for(Goods goods : goodsList){
            if(goods.getSubscription()!=null&&goods.getSubscription().compareTo(BigDecimal.ZERO)>0){
        for (Goods goods : goodsList) {
            if (goods.getSubscription() != null && goods.getSubscription().compareTo(BigDecimal.ZERO) > 0) {
                haveDeposit = true;
            }
        }
@@ -174,7 +194,7 @@
        // 将优惠券列表转换为Map,以优惠券ID为键
        Map<String, AppMemberCouponVo> appMemberCouponVoMap = new HashMap<>();
        if(appMemberCouponVoList!=null&&!appMemberCouponVoList.isEmpty()){
        if (appMemberCouponVoList != null && !appMemberCouponVoList.isEmpty()) {
            appMemberCouponVoMap = appMemberCouponVoList.stream().collect(Collectors.toMap(AppMemberCouponVo::getMemberCouponId, Function.identity()));
        }
        AppMemberCouponVo appMemberCouponVo;
@@ -201,7 +221,7 @@
            memberCouponId = appBuyGoodsDto.getMemberCouponId();
            // 获取商品信息
            goods = goodsMap.get(goodsId);
            if(goods.getGoodsStatus()!=1){
            if (goods.getGoodsStatus() != 1) {
                throw new ServiceException(AppErrorConstant.GOODS_DOWN);
            }
            // 设置订单商品信息
@@ -234,7 +254,7 @@
                    if (couponType == 1 && appMemberCouponVo.getMoneyThreshold() != null && appMemberCouponVo.getDiscountMoney() != null) {
                        moneyThreshold = appMemberCouponVo.getMoneyThreshold();
                        discountMoney = appMemberCouponVo.getDiscountMoney();
                        if (goodsTotalPrice.compareTo(moneyThreshold) >= 0 && goodsTotalPrice.compareTo(discountMoney)>0) {
                        if (goodsTotalPrice.compareTo(moneyThreshold) >= 0 && goodsTotalPrice.compareTo(discountMoney) > 0) {
                            goodsRealPrice = goodsTotalPrice.subtract(discountMoney);
                            useCoupon = 1;
                            userCouponIdSet.add(memberCouponId);
@@ -242,16 +262,16 @@
                        }
                    } else if (couponType == 2 && appMemberCouponVo.getDiscountPercent() != null) {
                        discountPercent = appMemberCouponVo.getDiscountPercent();
                        goodsRealPrice = goodsTotalPrice.multiply(discountPercent).divide(BigDecimal.TEN,2,BigDecimal.ROUND_HALF_UP);
                        goodsRealPrice = goodsTotalPrice.multiply(discountPercent).divide(BigDecimal.TEN, 2, BigDecimal.ROUND_HALF_UP);
                        discountMoney = goodsTotalPrice.subtract(goodsRealPrice);
                        useCoupon = 1;
                        userCouponIdSet.add(memberCouponId);
                        appSureOrderGoodsVo.setMemberCouponId(memberCouponId);
                    } else if (couponType == 3 && appMemberCouponVo.getDiscountMoney() != null) {
                        discountMoney = appMemberCouponVo.getDiscountMoney();
                        if(goodsTotalPrice.compareTo(discountMoney)>0){
                        if (goodsTotalPrice.compareTo(discountMoney) > 0) {
                            goodsRealPrice = goodsTotalPrice.subtract(discountMoney);
                            if(goodsRealPrice.compareTo(BigDecimal.ZERO)<0){
                            if (goodsRealPrice.compareTo(BigDecimal.ZERO) < 0) {
                                goodsRealPrice = BigDecimal.ZERO;
                            }
                            useCoupon = 1;
@@ -267,12 +287,12 @@
            appSureOrderGoodsVo.setGoodsRealPrice(goodsRealPrice);
            // 获取商品押金
            goodsDeposit = goods.getSubscription();
            if (goodsDeposit != null && goodsDeposit.compareTo(BigDecimal.ZERO)>0) {
            if (goodsDeposit != null && goodsDeposit.compareTo(BigDecimal.ZERO) > 0) {
                goodsDeposit = goodsDeposit.multiply(buyNumBig);
            }else{
                if(haveDeposit){
            } else {
                if (haveDeposit) {
                    goodsDeposit = goodsRealPrice;
                }else{
                } else {
                    goodsDeposit = new BigDecimal("0.00");
                }
            }
@@ -287,9 +307,9 @@
        //处理优惠券列表
        if (appMemberCouponVoList != null && !appMemberCouponVoList.isEmpty()) {
            for (AppMemberCouponVo entity : appMemberCouponVoList) {
                if(userCouponIdSet!=null&&userCouponIdSet.contains(entity.getMemberCouponId())){
                if (userCouponIdSet != null && userCouponIdSet.contains(entity.getMemberCouponId())) {
                    entity.setUseFlag(1);
                }else{
                } else {
                    entity.setUseFlag(0);
                }
@@ -297,18 +317,18 @@
            }
            // 过滤商品优惠券列表
            List<AppMemberCouponVo> appGoodsMemberCouponVoList;
            for(AppSureOrderGoodsVo sureOrderGoodsVo : appSureOrderGoodsVoList) {
            for (AppSureOrderGoodsVo sureOrderGoodsVo : appSureOrderGoodsVoList) {
                appGoodsMemberCouponVoList = new ArrayList<>();
                for(AppMemberCouponVo entity : appMemberCouponVoList){
                    if(StringUtils.isBlank(entity.getRelGoodsIds())||entity.getRelGoodsIds().contains(sureOrderGoodsVo.getGoodsId())){
                        if(entity.getCouponType()==1){
                            if(entity.getMoneyThreshold().compareTo(sureOrderGoodsVo.getGoodsTotalPrice())<0&&entity.getDiscountMoney().compareTo(sureOrderGoodsVo.getGoodsTotalPrice())<0){
                for (AppMemberCouponVo entity : appMemberCouponVoList) {
                    if (StringUtils.isBlank(entity.getRelGoodsIds()) || entity.getRelGoodsIds().contains(sureOrderGoodsVo.getGoodsId())) {
                        if (entity.getCouponType() == 1) {
                            if (entity.getMoneyThreshold().compareTo(sureOrderGoodsVo.getGoodsTotalPrice()) < 0 && entity.getDiscountMoney().compareTo(sureOrderGoodsVo.getGoodsTotalPrice()) < 0) {
                                appGoodsMemberCouponVoList.add(entity);
                            }
                        }else if(entity.getCouponType()==2){
                        } else if (entity.getCouponType() == 2) {
                            appGoodsMemberCouponVoList.add(entity);
                        }else if(entity.getCouponType()==3){
                            if(entity.getDiscountMoney().compareTo(sureOrderGoodsVo.getGoodsTotalPrice())<0){
                        } else if (entity.getCouponType() == 3) {
                            if (entity.getDiscountMoney().compareTo(sureOrderGoodsVo.getGoodsTotalPrice()) < 0) {
                                appGoodsMemberCouponVoList.add(entity);
                            }
                        }
@@ -415,8 +435,8 @@
        if (activityGoodsGetVo.getActivityStatus() == 2) {
            throw new ServiceException(AppErrorConstant.ACTIVITY_END);
        }
        Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+activityId+"-"+goodsId);
        if(surpNum==null||surpNum<1){
        Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + activityId + "-" + goodsId);
        if (surpNum == null || surpNum < 1) {
            throw new ServiceException(AppErrorConstant.ACTIVITY_GOODS_NULL);
        }
        if (activityGoodsGetVo.getAvailableBuyNum() < 1) {
@@ -426,7 +446,7 @@
            throw new ServiceException(AppErrorConstant.ACTIVITY_GOODS_BEYOND);
        }
        Goods goods = remoteGoodsService.getGoods(goodsId).getData();
        if(goods.getGoodsStatus()!=1){
        if (goods.getGoodsStatus() != 1) {
            throw new ServiceException(AppErrorConstant.GOODS_DOWN);
        }
        appPanicBuyVo.setActivityId(activityId);
@@ -456,9 +476,9 @@
        appPanicBuyVo.setGoodsTotalPrice(goodsTotalPrice);
        appPanicBuyVo.setGoodsRealPrice(goodsRealPrice);
        goodsDeposit = activityGoodsGetVo.getActivitySubscription();
        if (goodsDeposit == null || goodsDeposit.compareTo(BigDecimal.ZERO)==0) {
        if (goodsDeposit == null || goodsDeposit.compareTo(BigDecimal.ZERO) == 0) {
            goodsDeposit = new BigDecimal("0.00");
        }else{
        } else {
            goodsDeposit = goodsDeposit.multiply(buyNumBig);
        }
        appPanicBuyVo.setGoodsDeposit(goodsDeposit);
@@ -498,8 +518,8 @@
        Map<String, Goods> goodsMap = goodsList.stream()
                .collect(Collectors.toMap(Goods::getGoodsId, Function.identity()));
        Boolean haveDeposit = false;
        for(Goods goods : goodsList){
            if(goods.getSubscription()!=null&&goods.getSubscription().compareTo(BigDecimal.ZERO)>0){
        for (Goods goods : goodsList) {
            if (goods.getSubscription() != null && goods.getSubscription().compareTo(BigDecimal.ZERO) > 0) {
                haveDeposit = true;
            }
        }
@@ -510,7 +530,7 @@
        Integer serviceNum;
        Integer goodsNum = 0;
        String memberCouponId;
        Goods goods;
        Goods goods = null;
        GoodsFile goodsFile;
        BigDecimal goodsPrice;
        BigDecimal goodsTotalPrice;
@@ -542,6 +562,7 @@
        HashSet<String> goodsTypeSet = new HashSet<>();
        //使用优惠券
        StringJoiner memberCouponSJ = new StringJoiner(",");
        List<String> goodsNameList = new ArrayList<>();
        // 遍历购买的商品列表
        for (AppBuyGoodsDto appBuyGoodsDto : appBuyGoodsDtoList) {
            appSureOrderGoodsVo = new AppSureOrderGoodsVo();
@@ -551,6 +572,7 @@
            memberCouponId = appBuyGoodsDto.getMemberCouponId();
            // 获取商品信息
            goods = goodsMap.get(goodsId);
            goodsNameList.add(goods.getGoodsName());
            // 设置商品信息
            appSureOrderGoodsVo.setGoodsId(goodsId);
            appSureOrderGoodsVo.setGoodsName(goods.getGoodsName());
@@ -596,7 +618,7 @@
                        }
                    } else if (couponType == 2 && appMemberCouponVo.getDiscountPercent() != null) {
                        discountPercent = appMemberCouponVo.getDiscountPercent();
                        goodsRealPrice = goodsTotalPrice.multiply(discountPercent).divide(BigDecimal.TEN,2, BigDecimal.ROUND_HALF_UP);
                        goodsRealPrice = goodsTotalPrice.multiply(discountPercent).divide(BigDecimal.TEN, 2, BigDecimal.ROUND_HALF_UP);
                        discountMoney = goodsTotalPrice.subtract(goodsRealPrice);
                        useCoupon = 1;
                    } else if (couponType == 3 && appMemberCouponVo.getDiscountMoney() != null) {
@@ -613,12 +635,12 @@
            appSureOrderGoodsVo.setGoodsRealPrice(goodsRealPrice);
            // 获取商品押金
            goodsDeposit = goods.getSubscription();
            if (goodsDeposit != null && goodsDeposit.compareTo(BigDecimal.ZERO)>0) {
            if (goodsDeposit != null && goodsDeposit.compareTo(BigDecimal.ZERO) > 0) {
                goodsDeposit = goodsDeposit.multiply(buyNumBig);
            }else{
                if(haveDeposit){
            } else {
                if (haveDeposit) {
                    goodsDeposit = goodsRealPrice;
                }else{
                } else {
                    goodsDeposit = new BigDecimal("0.00");
                }
            }
@@ -714,53 +736,127 @@
        }
        appPlaceOrderVo.setOrderId(orderId);
        appPlaceOrderVo.setOrderNo(orderNo);
        // 调用支付
       /* CombineTransactionsJsRequest request=new CombineTransactionsJsRequest();
        request.setCombineAppid();
        request.setCombineMchid();
        profitsSharingService.combineTransactions(request);*/
       //构建预下单支付对象
        /*PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(Integer.parseInt(order.getPayMoney().multiply(new BigDecimal(100)).toString()));
        request.setAmount(amount);
        request.setAppid(this.appId);
        request.setMchid(this.mchId);
        request.setDescription(order.getGoodsInfo());
        request.setNotifyUrl(this.notifyUrl);
        request.setOutTradeNo(order.getOrderId());
        Payer payer = new Payer();
        payer.setOpenid("oLTPCuN5a-nBD4rAL_fa********");
        request.setPayer(payer);*/
        //返回前端唤醒支付结果信息
        /*PrepayWithRequestPaymentResponse res = this.getJsApIResponse(request);
        appPlaceOrderVo.setAppId(this.appId);
        appPlaceOrderVo.setTimeStamp(res.getTimeStamp());
        appPlaceOrderVo.setNonceStr(res.getNonceStr());
        appPlaceOrderVo.setPackageStr(res.getPackageVal());
        appPlaceOrderVo.setTradeType(res.getSignType());
        appPlaceOrderVo.setPaySign(res.getPaySign());*/
        String goodsName = "";
        if (null != goods) {
            goodsName = goods.getGoodsName();
        }
        // 小程序微信下单支付
        createWxPayInfo(appPlaceOrderVo, userId, order.getShopId(), goodsName, orderNo,
                orderId, order.getPayMoney(), appPlaceOrderDto.getOpenid(),
                appPlaceOrderDto.getSpbillCreateIp(), goodsNameList);
        //减去优惠券
        if(memberCouponSJ!=null&&StringUtils.isNotBlank(memberCouponSJ.toString())){
        if (StringUtils.isNotBlank(memberCouponSJ.toString())) {
            remoteCouponService.useMemberCoupon(memberCouponSJ.toString());
        }
        //生成自动取消订单延时任务
        Integer delayTime = 30;
        if(redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)){
        if (redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)) {
            delayTime = redisService.getCacheObject(SecurityConstant.AUTO_CANCEL_ORDER_TIME);
        }
        redisService.setCacheObject(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + orderId, orderId, delayTime.longValue(), TimeUnit.MINUTES);
        DelayTask delayTask = new DelayTask();
        delayTask.setDelFlag(0);
        delayTask.setCreateTime(new Date());
        delayTask.setEndTime(DateUtils.addMinutes(new Date(),delayTime));
        delayTask.setEndTime(DateUtils.addMinutes(new Date(), delayTime));
        delayTask.setRedisKey(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + orderId);
        remoteConfigService.addDelayTask(delayTask);
        appPlaceOrderVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(),delayTime));
        appPlaceOrderVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(), delayTime));
        return appPlaceOrderVo;
    }
    /**
     * 小程序支付下单API
     * @param appPlaceOrderVo
     * @param userId
     * @param shopId
     * @param goodsName
     * @param orderNo
     * @param orderId
     * @param payMoney
     * @param openid
     * @param payerClientIp
     * @param goodsNameList
     */
    private void createWxPayInfo(AppPlaceOrderVo appPlaceOrderVo, Long userId, Long shopId,
                                 String goodsName, String orderNo,
                                 String orderId, BigDecimal payMoney,
                                 String openid, String payerClientIp, List<String> goodsNameList){
        try {
            // 创建支付订单
            R<String> resultMch = remoteShopService.getShopSubMchId(shopId);
            String subMchId = resultMch.getData();
            if (StringUtils.isEmpty(subMchId)) {
                throw new ServiceException("获取微信商户号失败");
            }
            WxPayConfig config = wxService.getConfig();
            config.setSubMchId(subMchId);
            PartnerTransactionsRequest request = new PartnerTransactionsRequest();
            request.setSpAppid(config.getAppId());
            request.setSpMchid(config.getMchId());
            request.setSubMchid(config.getSubMchId());
            //  商品描述    body
            String description = goodsName + "-商品购买";
            request.setDescription(description);
            request.setOutTradeNo(orderNo);
            request.setNotifyUrl(config.getNotifyUrl());
            // 结算信息
            PartnerTransactionsRequest.SettleInfo settleInfo = new PartnerTransactionsRequest.SettleInfo();
            settleInfo.setProfitSharing(true);
            settleInfo.setSubsidyAmount(BigDecimal.ZERO);
            request.setSettleInfo(settleInfo);
            // 订单总金额
            Integer totalFee = payMoney.multiply(new BigDecimal(100)).intValue();
            PartnerTransactionsRequest.Amount amount = new PartnerTransactionsRequest.Amount();
            amount.setTotal(totalFee);
            amount.setCurrency("CNY");
            request.setAmount(amount);
            // 支付者
            PartnerTransactionsRequest.Payer payer = new PartnerTransactionsRequest.Payer();
            payer.setSpOpenid(openid);
            request.setPayer(payer);
            // 场景信息
            PartnerTransactionsRequest.SceneInfo sceneInfo = new PartnerTransactionsRequest.SceneInfo();
            sceneInfo.setPayerClientIp(payerClientIp);
            request.setSceneInfo(sceneInfo);
            TransactionsResult.JsapiResult result = wxService.getEcommerceService().partnerTransactions(TradeTypeEnum.JSAPI, request);
            // 请求参数
            Gson gson = new Gson();
            String payRequestJson = gson.toJson(request);
            // 返回参数
            String payResponseJson = gson.toJson(result);
            // 支付相关信息返回
            appPlaceOrderVo.setAppId(result.getAppId());
            appPlaceOrderVo.setMchId(config.getMchId());
            appPlaceOrderVo.setTimeStamp(result.getTimeStamp());
            appPlaceOrderVo.setNonceStr(result.getNonceStr());
            appPlaceOrderVo.setPackageStr(result.getPackageValue());
            appPlaceOrderVo.setSignType(result.getSignType());
            appPlaceOrderVo.setPaySign(result.getPaySign());
            appPlaceOrderVo.setPrepayId(result.getPackageValue());
            // 保存支付订单统一下单日志
            paymentMessageService.savePaymentMessage("1", orderId, payRequestJson, payResponseJson);
            // 保存支付订单统一下单支付记录
            orderPaymentService.saveOrderPayment(userId, shopId, subMchId, orderId, payMoney,
                    appPlaceOrderVo.getEndTime(), "Y", openid,
                    Joiner.on(";").join(goodsNameList), result.getPackageValue());
        } catch (WxPayException e) {
            throw new ServiceException(e.getMessage());
        }
    }
@@ -784,17 +880,17 @@
        String goodsId = appPlaceActivityDto.getGoodsId();
        Integer buyNum = appPlaceActivityDto.getBuyNum();
        //redis库存控制极简版
        String goodsLock = "goods_lock_"+activityId+"_"+goodsId;
        String goodsLock = "goods_lock_" + activityId + "_" + goodsId;
        RLock redissonLock = redissonClient.getLock(goodsLock);
        try{
        try {
            redissonLock.lock(30, TimeUnit.SECONDS);
            Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+activityId+"-"+goodsId);
            if(surpNum==null||surpNum<buyNum){
            Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + activityId + "-" + goodsId);
            if (surpNum == null || surpNum < buyNum) {
                throw new ServiceException(AppErrorConstant.ACTIVITY_GOODS_NULL);
            }else{
                redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+activityId+"-"+goodsId,surpNum-buyNum);
            } else {
                redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + activityId + "-" + goodsId, surpNum - buyNum);
            }
        }finally{
        } finally {
            redissonLock.unlock();
        }
        // 定义购买数量,服务数量,商品数量
@@ -874,9 +970,9 @@
        appSureOrderGoodsVo.setGoodsRealPrice(goodsRealPrice);
        // 获取商品押金
        goodsDeposit = activityGoodsGetVo.getActivitySubscription();
        if (goodsDeposit == null || goodsDeposit.compareTo(BigDecimal.ZERO)==0) {
        if (goodsDeposit == null || goodsDeposit.compareTo(BigDecimal.ZERO) == 0) {
            goodsDeposit = new BigDecimal("0.00");
        }else{
        } else {
            goodsDeposit = goodsDeposit.multiply(buyNumBig);
        }
        appSureOrderGoodsVo.setGoodsDeposit(goodsDeposit);
@@ -923,9 +1019,9 @@
            goodsTypeSet.add("单品");
        }
        String goodsNurse = goods.getGoodsNurses();
        if(StringUtils.isNotBlank(goodsNurse)){
        if (StringUtils.isNotBlank(goodsNurse)) {
            String[] goodsNurseArr = goodsNurse.split(",");
            for(String str : goodsNurseArr){
            for (String str : goodsNurseArr) {
                goodsNurseSet.add(str);
            }
        }
@@ -969,7 +1065,7 @@
        // 保存订单
        this.save(order);
        // 更新用户商品类型
        if (goodsTypeSet != null || goodsNurseSet!= null) {
        if (goodsTypeSet != null || goodsNurseSet != null) {
            AppMemberGoodsTypeDto appMemberGoodsTypeDto = new AppMemberGoodsTypeDto();
            appMemberGoodsTypeDto.setUserId(userId);
            appMemberGoodsTypeDto.setGoodsTypeSet(goodsTypeSet);
@@ -1037,17 +1133,17 @@
        remoteActivityService.addActivityRecord(activityRecord);
        //生成自动取消订单延时任务
        Integer delayTime = 30;
        if(redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)){
        if (redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)) {
            delayTime = redisService.getCacheObject(SecurityConstant.AUTO_CANCEL_ORDER_TIME);
        }
        redisService.setCacheObject(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + orderId, orderId, delayTime.longValue(), TimeUnit.MINUTES);
        DelayTask delayTask = new DelayTask();
        delayTask.setDelFlag(0);
        delayTask.setCreateTime(new Date());
        delayTask.setEndTime(DateUtils.addMinutes(new Date(),delayTime));
        delayTask.setEndTime(DateUtils.addMinutes(new Date(), delayTime));
        delayTask.setRedisKey(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + orderId);
        remoteConfigService.addDelayTask(delayTask);
        appPlaceOrderVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(),delayTime));
        appPlaceOrderVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(), delayTime));
        return appPlaceOrderVo;
    }
@@ -1076,7 +1172,7 @@
                shopMap.put(shopIdLong, shopTemp);
            });
            Integer delayTime = 30;
            if(redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)){
            if (redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)) {
                delayTime = redisService.getCacheObject(SecurityConstant.AUTO_CANCEL_ORDER_TIME);
            }
            for (AppUserOrderPageVo appUserOrderPageVo : appUserOrderPageVoList) {
@@ -1089,7 +1185,7 @@
                    appUserOrderPageVo.setSameShop(0);
                }
                appUserOrderPageVo.setVerifyCode("1-" + appUserOrderPageVo.getOrderId());
                appUserOrderPageVo.setEndTime(DateUtils.addMinutes(appUserOrderPageVo.getCreateTime(),delayTime));
                appUserOrderPageVo.setEndTime(DateUtils.addMinutes(appUserOrderPageVo.getCreateTime(), delayTime));
            }
        }
        return appUserOrderPageVoList;
@@ -1130,10 +1226,10 @@
        appUserOrderGetVo.setVerifyCode("1-" + orderId);
        //生成自动取消订单延时任务
        Integer delayTime = 30;
        if(redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)){
        if (redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)) {
            delayTime = redisService.getCacheObject(SecurityConstant.AUTO_CANCEL_ORDER_TIME);
        }
        appUserOrderGetVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(),delayTime));
        appUserOrderGetVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(), delayTime));
        return appUserOrderGetVo;
    }
@@ -1145,13 +1241,15 @@
    @Override
    public void cancelOrder(String orderId) {
        Order order = this.getById(orderId);
        // 订单状态-1.删除 0.已取消 1.待支付 2.待核销 3.已完成
        if (order.getOrderStatus() == 0) {
            throw new ServiceException(AppErrorConstant.CANCEL_CANCEL_ORDER);
        }else if (order.getOrderStatus() == 1) {
        } else if (order.getOrderStatus() == 1) {
            this.autoCancelOrder(orderId);
        }else if(order.getOrderStatus() == 2){
        } else if (order.getOrderStatus() == 2) {
            // 2.待核销 -> 订单退款
            this.refundOrder(orderId);
        }else{
        } else {
            throw new ServiceException(AppErrorConstant.CANCEL_ERROR_ORDER);
        }
    }
@@ -1267,7 +1365,7 @@
        }
        ShopRelUserVo shopRelUserVo = remoteShopService.getShopByUserId(merVerifyOrderDto.getUserId()).getData();
        if(!shopRelUserVo.getShopId().equals(order.getShopId())){
        if (!shopRelUserVo.getShopId().equals(order.getShopId())) {
            throw new ServiceException(AppErrorConstant.VERIFY_SHOP_ERROR);
        }
        order.setOrderStatus(3);
@@ -1277,9 +1375,9 @@
        order.setOffPayTime(nowTime);
        order.setPayMoney(order.getPayMoney().add(relPayMoney));
        order.setChangeReceivableMoney(relReceiveMoney);
        if(order.getPayMoney().compareTo(order.getChangeReceivableMoney())>=0){
        if (order.getPayMoney().compareTo(order.getChangeReceivableMoney()) >= 0) {
            order.setCloseFlag(1);
        }else{
        } else {
            order.setCloseFlag(0);
        }
        this.saveOrUpdate(order);
@@ -1299,7 +1397,7 @@
        List<ConsumerGoods> consumerGoodsList = new ArrayList<>();
        for (AppUserOrderGoodsPageVo appUserOrderGoodsPageVo : appUserOrderGoodsPageVoList) {
            Integer buyNum = appUserOrderGoodsPageVo.getBuyNum();
            if(appUserOrderGoodsPageVo.getCycleNumFlag()==0){
            if (appUserOrderGoodsPageVo.getCycleNumFlag() == 0) {
                consumerGoods = new ConsumerGoods();
                goods = goodsMap.get(appUserOrderGoodsPageVo.getGoodsId());
                consumerGoodsId = IdUtils.simpleUUID();
@@ -1324,8 +1422,8 @@
                consumerGoods.setSourceFrom(1);
                consumerGoods.setSureNum(buyNum);
                consumerGoodsList.add(consumerGoods);
            }else{
                for(int i=0;i<buyNum;i++){
            } else {
                for (int i = 0; i < buyNum; i++) {
                    consumerGoods = new ConsumerGoods();
                    goods = goodsMap.get(appUserOrderGoodsPageVo.getGoodsId());
                    consumerGoodsId = IdUtils.simpleUUID();
@@ -1386,9 +1484,8 @@
        merVerifyOrderVo.setUserMobile(member.getMobile());
        merVerifyOrderVo.setCloseFlag(order.getCloseFlag());
        //
        if(order.getOrderFrom()==2){
            //profitsSharingService.applyProfitSharing();
        if (order.getOrderFrom() == 2) {
            // profitsSharingService.applyProfitSharing();
        }
        //创建支付记录
@@ -1399,8 +1496,87 @@
        payRecord.setPayTime(new Date());
        payRecord.setPayType(merVerifyOrderDto.getPayType());
        payRecordService.save(payRecord);
        return merVerifyOrderVo;
        submitProfitSharing(orderId, order.getOrderNo(), order.getShopId(), order.getOrderMoney());
        return merVerifyOrderVo;
    }
    private void submitProfitSharing(String orderId, String orderNo, Long shopId, BigDecimal orderMoney) {
        String sendMessage = "";
        String resultMessage = "";
        try {
            // 核销完成 开始分账(平台收取服务费)
            OrderPayment payment = orderPaymentService.getByOrderId(orderId);
            String transactionId = payment.getTransactionId();
            // 平台特约商户号,用户平台收取服务费
            String platformTyMacId = WxPayConfiguration.getPlatformTyMacId();
            R<String> resultMch = remoteShopService.getShopSubMchId(shopId);
            String subMchId = resultMch.getData();
            if (!StringUtils.isEmpty(subMchId)) {
                R<ShopProportionVo> resultShopProportion = remoteShopService.getShopProportion(shopId);
                ShopProportionVo shopProportion = resultShopProportion.getData();
                if (null != shopProportion) {
                    ProfitSharingRequest request = new ProfitSharingRequest();
                    request.setSubMchid(subMchId);
                    request.setTransactionId(transactionId);
                    request.setOutOrderNo(orderNo);
                    List<Receiver> receiverList = new ArrayList<>();
                    String description = "订单:" + orderNo + " 平台抽取佣金";
                    BigDecimal proportionPercent = shopProportion.getProportionPercent();
                    if (null == proportionPercent) {
                        proportionPercent = BigDecimal.ZERO;
                    }
                    ProfitSharingResult result = new ProfitSharingResult();
                    result.setOutOrderNo(orderNo);
                    result.setStatus("FINISHED");
                    // 计算分成金额
                    int amount = orderMoney.multiply(proportionPercent).setScale(0, RoundingMode.UP).intValue();
                    log.info("订单分账:{} 分账金额: {}", orderNo, amount);
                    if (amount > 0) {
                        // 分账创建
                        Receiver receiver = new Receiver();
                        receiver.setType("MERCHANT_ID");
                        receiver.setReceiverAccount(platformTyMacId);
                        receiver.setAmount(amount);
                        receiver.setDescription(description);
                        receiverList.add(receiver);
                        request.setReceivers(receiverList);
                        // 分账完成
                        request.setFinish(true);
                        result = wxService.getEcommerceService().profitSharing(request);
                    }
                    // 创建分账记录
                    profitSharingService.saveProfitSharing(shopId, orderId, orderMoney, result);
                    // 保存请求信息
                    sendMessage = JSONObject.toJSONString(request);
                    resultMessage = JSONObject.toJSONString(result);
                } else {
                    resultMessage = String.format("订单分账:%s 获取商户分成失败", orderNo);
                    log.info(resultMessage);
                }
            } else {
                resultMessage = String.format("订单分账:%s 获取微信商户号失败", orderNo);
                log.info(resultMessage);
            }
        } catch (WxPayException e) {
            resultMessage = String.format("订单分账:%s 分账失败:%s", orderNo, e.getMessage());
            log.info(resultMessage);
            e.printStackTrace();
        }
        // 保存分账信息
        paymentMessageService.savePaymentMessage("4", orderId, sendMessage, resultMessage);
    }
    /**
@@ -1415,7 +1591,7 @@
    public MerVerifyCouponVo sureVerifyCoupon(MerVerifyCouponDto merVerifyCouponDto) {
        MerVerifyCouponGetVo verifyCouponGetVo = remoteCouponService.getVerifyCoupon(merVerifyCouponDto.getMemberCouponId()).getData();
        ShopRelUserVo shopRelUserVo = remoteShopService.getShopByUserId(merVerifyCouponDto.getUserId()).getData();
        if(!shopRelUserVo.getShopId().equals(verifyCouponGetVo.getMemberCoupon().getShopId())){
        if (!shopRelUserVo.getShopId().equals(verifyCouponGetVo.getMemberCoupon().getShopId())) {
            throw new ServiceException(AppErrorConstant.VERIFY_SHOP_ERROR);
        }
        // 创建MerVerifyCouponVo对象
@@ -1478,7 +1654,7 @@
            appShopGoodsGetDto.setShopId(memberCoupon.getShopId());
            //获取商户服务次数
            shopGoods = remoteGoodsService.getShopGoods(appShopGoodsGetDto).getData();
            if(shopGoods!=null){
            if (shopGoods != null) {
                consumerGoods.setServiceNum(shopGoods.getServiceNum());
            }
            consumerGoods.setUsedNum(0);
@@ -1499,36 +1675,36 @@
    /**
     * @description  确认核销奖品
     * @author  jqs
     * @date    2023/7/9 9:54
     * @param merVerifyPrizeDto
     * @return  MerVerifyAwardVo
     * @return MerVerifyAwardVo
     * @description 确认核销奖品
     * @author jqs
     * @date 2023/7/9 9:54
     */
    @Override
    @Transactional
    public MerVerifyAwardVo sureVerifyPrize(MerVerifyPrizeDto merVerifyPrizeDto){
    public MerVerifyAwardVo sureVerifyPrize(MerVerifyPrizeDto merVerifyPrizeDto) {
        MerVerifyAwardVo merVerifyAwardVo = new MerVerifyAwardVo();
        MemberGiftRecord memberGiftRecord = remoteMemberService.getVerifyPrize(merVerifyPrizeDto.getPrizeId()).getData();
        if(memberGiftRecord==null||memberGiftRecord.getVerifyStatus()!=1){
        if (memberGiftRecord == null || memberGiftRecord.getVerifyStatus() != 1) {
            throw new ServiceException(AppErrorConstant.COUPON_USED);
        }
        ShopRelUserVo shopRelUserVo = remoteShopService.getShopByUserId(merVerifyPrizeDto.getUserId()).getData();
        if(!shopRelUserVo.getShopId().equals(memberGiftRecord.getShopId())){
        if (!shopRelUserVo.getShopId().equals(memberGiftRecord.getShopId())) {
            throw new ServiceException(AppErrorConstant.VERIFY_SHOP_ERROR);
        }
        Member member = remoteMemberService.getMember(memberGiftRecord.getUserId()).getData();
        merVerifyAwardVo.setUserName(member.getRealName());
        merVerifyAwardVo.setUserMobile(member.getMobile());
        if(memberGiftRecord.getGiftFrom()==1){
        if (memberGiftRecord.getGiftFrom() == 1) {
            merVerifyAwardVo.setGiftFrom("平台生日卡");
        }else{
        } else {
            merVerifyAwardVo.setGiftFrom("商户生日卡");
        }
        merVerifyAwardVo.setGiftType(memberGiftRecord.getGiftType());
        List<BirthdayGiftSendDto> giftSendDtoList = new ArrayList<>();
        BirthdayGiftSendDto birthdayGiftSendDto = new BirthdayGiftSendDto();
        switch(memberGiftRecord.getGiftType()){
        switch (memberGiftRecord.getGiftType()) {
            case 1:
                merVerifyAwardVo.setGiftName(memberGiftRecord.getCouponName());
                merVerifyAwardVo.setGiftNumber(Double.valueOf(memberGiftRecord.getCouponNumber()));
@@ -1577,7 +1753,7 @@
        merVerifyAwardVo.setCreateTime(memberGiftRecord.getCreateTime());
        memberGiftRecord.setVerifyStatus(2);
        memberGiftRecord.setVerifyTime(new Date());
        if(member.getBindingFlag()!=1){
        if (member.getBindingFlag() != 1) {
            AppMemberBindingDto appMemberBindingDto = new AppMemberBindingDto();
            appMemberBindingDto.setBindingFlag(1);
            appMemberBindingDto.setShopId(merVerifyPrizeDto.getShopId());
@@ -1625,9 +1801,9 @@
        order.setOfflinePayMoney(order.getOfflinePayMoney().add(merCloseOrderDto.getPayMoney()));
        order.setOffPayTime(new Date());
        order.setPayMoney(order.getPayMoney().add(merCloseOrderDto.getPayMoney()));
        if(order.getPayMoney().compareTo(order.getChangeReceivableMoney())>=0){
        if (order.getPayMoney().compareTo(order.getChangeReceivableMoney()) >= 0) {
            order.setCloseFlag(0);
        }else{
        } else {
            order.setCloseFlag(1);
        }
        this.saveOrUpdate(order);
@@ -1758,7 +1934,7 @@
                        }
                    } else if (couponType == 2 && appMemberCouponVo.getDiscountPercent() != null) {
                        discountPercent = appMemberCouponVo.getDiscountPercent();
                        goodsRealPrice = goodsTotalPrice.multiply(discountPercent).divide(BigDecimal.TEN,2, BigDecimal.ROUND_HALF_UP);
                        goodsRealPrice = goodsTotalPrice.multiply(discountPercent).divide(BigDecimal.TEN, 2, BigDecimal.ROUND_HALF_UP);
                        discountMoney = goodsRealPrice.subtract(goodsTotalPrice);
                    } else if (couponType == 3 && appMemberCouponVo.getDiscountMoney() != null) {
                        discountMoney = appMemberCouponVo.getDiscountMoney();
@@ -1768,9 +1944,9 @@
            }
            goodsDeposit = goods.getSubscription();
            if (goodsDeposit == null || goodsDeposit.compareTo(BigDecimal.ZERO)==0) {
            if (goodsDeposit == null || goodsDeposit.compareTo(BigDecimal.ZERO) == 0) {
                goodsDeposit = new BigDecimal("0.00");
            }else{
            } else {
                goodsDeposit = goodsDeposit.multiply(buyNumBig);
            }
            goodsNum = goodsNum + buyNum;
@@ -1850,9 +2026,9 @@
        order.setOfflinePayMoney(merNewOrderDto.getPayMoney());
        order.setOffPayTime(nowTime);
        order.setPayType(1);
        if(order.getPayMoney().compareTo(order.getChangeReceivableMoney())>=0){
        if (order.getPayMoney().compareTo(order.getChangeReceivableMoney()) >= 0) {
            order.setCloseFlag(0);
        }else{
        } else {
            order.setCloseFlag(1);
        }
        this.save(order);
@@ -1863,7 +2039,7 @@
        List<ConsumerGoods> consumerGoodsList = new ArrayList<>();
        for (AppUserOrderGoodsPageVo appUserOrderGoodsPageVo : appUserOrderGoodsPageVoList) {
            Integer buyGoodsNum = appUserOrderGoodsPageVo.getBuyNum();
            if(appUserOrderGoodsPageVo.getCycleNumFlag()==0){
            if (appUserOrderGoodsPageVo.getCycleNumFlag() == 0) {
                consumerGoods = new ConsumerGoods();
                goods = remoteGoodsService.getGoods(appUserOrderGoodsPageVo.getGoodsId()).getData();
                consumerGoodsId = IdUtils.simpleUUID();
@@ -1888,8 +2064,8 @@
                consumerGoods.setSourceFrom(1);
                consumerGoods.setSureNum(buyGoodsNum);
                consumerGoodsList.add(consumerGoods);
            }else{
                for(int i=0;i<buyGoodsNum;i++) {
            } else {
                for (int i = 0; i < buyGoodsNum; i++) {
                    consumerGoods = new ConsumerGoods();
                    goods = remoteGoodsService.getGoods(appUserOrderGoodsPageVo.getGoodsId()).getData();
                    consumerGoodsId = IdUtils.simpleUUID();
@@ -1952,11 +2128,11 @@
     */
    @Override
    public List<MerOrderPageVo> pageMerOrder(Page page, MerOrderPageDto merOrderPageDto) {
        if(StringUtils.isNotBlank(merOrderPageDto.getKeyword())){
        if (StringUtils.isNotBlank(merOrderPageDto.getKeyword())) {
            MgtUserIdByKeywordDto userIdByKeywordDto = new MgtUserIdByKeywordDto();
            userIdByKeywordDto.setKeyword(merOrderPageDto.getKeyword());
            MgtUserIdByKeywordVo userIdByKeywordVo = remoteMemberService.getUserIdByKeyword(userIdByKeywordDto).getData();
            if(StringUtils.isNotBlank(userIdByKeywordVo.getUserIds())){
            if (StringUtils.isNotBlank(userIdByKeywordVo.getUserIds())) {
                List<Long> userIdList = Arrays.stream(userIdByKeywordVo.getUserIds().split(","))
                        .map(Long::parseLong)
                        .collect(Collectors.toList());
@@ -2000,12 +2176,12 @@
            Map<Long, MgtSimpleMemberVo> userMap = simpleMemberVoList.stream()
                    .collect(Collectors.toMap(MgtSimpleMemberVo::getUserId, Function.identity()));
            for (MerOrderPageVo merOrderPageVo : merOrderPageVoList) {
                if(merOrderPageVo.getUserId()!=null&&userMap.get(merOrderPageVo.getUserId())!=null){
                if (merOrderPageVo.getUserId() != null && userMap.get(merOrderPageVo.getUserId()) != null) {
                    merOrderPageVo.setUserName(userMap.get(merOrderPageVo.getUserId()).getRealName());
                    merOrderPageVo.setNickName(userMap.get(merOrderPageVo.getUserId()).getNickName());
                    merOrderPageVo.setUserMobile(userMap.get(merOrderPageVo.getUserId()).getUserMobile());
                }else{
                    log.debug("订单merOrderPageVo"+merOrderPageVo.getOrderId()+"缺少用户");
                } else {
                    log.debug("订单merOrderPageVo" + merOrderPageVo.getOrderId() + "缺少用户");
                }
            }
        }
@@ -2372,9 +2548,9 @@
        mgtOrderDetailVo.setCancelTime(order.getCancelTime());
        mgtOrderDetailVo.setOrderRemark(order.getOrderRemark());
        mgtOrderDetailVo.setShopId(order.getShopId());
        if(shop!=null){
        if (shop != null) {
            mgtOrderDetailVo.setShopName(shop.getShopName());
        }else{
        } else {
            mgtOrderDetailVo.setShopName("商户已被删除");
        }
        mgtOrderDetailVo.setVerifyTime(order.getUseTime());
@@ -2966,11 +3142,11 @@
        } else if (couponStatus != 1) {
            throw new ServiceException(AppErrorConstant.COUPON_NO_FIND);
        }
        if (memberCoupon.getCouponFrom()==2&&!memberCoupon.getShopId().equals(shopId)) {
        if (memberCoupon.getCouponFrom() == 2 && !memberCoupon.getShopId().equals(shopId)) {
            throw new ServiceException(AppErrorConstant.VERIFY_SHOP_ERROR);
        }
        //如果是平台优惠券
        if(memberCoupon.getCouponFrom()==1&&memberCoupon.getShopId()==null){
        if (memberCoupon.getCouponFrom() == 1 && memberCoupon.getShopId() == null) {
            memberCoupon.setShopId(shopId);
        }
        List<Goods> goodsList = verifyCouponGetVo.getGoodsList();
@@ -3008,34 +3184,34 @@
    }
    /**
     * @description  获取核销奖品
     * @author  jqs
     * @date    2023/7/8 17:46
     * @param verifyCode
     * @param shopId
     * @return  MerVerifyAwardVo
     * @return MerVerifyAwardVo
     * @description 获取核销奖品
     * @author jqs
     * @date 2023/7/8 17:46
     */
    @Override
    public MerVerifyAwardVo verifyPrize(String verifyCode,Long shopId){
    public MerVerifyAwardVo verifyPrize(String verifyCode, Long shopId) {
        MerVerifyAwardVo merVerifyAwardVo = new MerVerifyAwardVo();
        MemberGiftRecord memberGiftRecord = remoteMemberService.getVerifyPrize(verifyCode).getData();
        if(memberGiftRecord==null||memberGiftRecord.getVerifyStatus()!=1){
        if (memberGiftRecord == null || memberGiftRecord.getVerifyStatus() != 1) {
            throw new ServiceException(AppErrorConstant.COUPON_USED);
        }
        if(memberGiftRecord.getGiftFrom()==2&&!memberGiftRecord.getShopId().equals(shopId)){
        if (memberGiftRecord.getGiftFrom() == 2 && !memberGiftRecord.getShopId().equals(shopId)) {
            throw new ServiceException(AppErrorConstant.VERIFY_SHOP_ERROR);
        }
        Member member = remoteMemberService.getMember(memberGiftRecord.getUserId()).getData();
        merVerifyAwardVo.setUserName(member.getRealName());
        merVerifyAwardVo.setUserMobile(member.getMobile());
        if(memberGiftRecord.getGiftFrom()==1){
        if (memberGiftRecord.getGiftFrom() == 1) {
            merVerifyAwardVo.setGiftFrom("平台生日卡");
        }else{
        } else {
            merVerifyAwardVo.setGiftFrom("商户生日卡");
        }
        merVerifyAwardVo.setGiftType(memberGiftRecord.getGiftType());
        switch(memberGiftRecord.getGiftType()){
        switch (memberGiftRecord.getGiftType()) {
            case 1:
                merVerifyAwardVo.setGiftName(memberGiftRecord.getCouponName());
                merVerifyAwardVo.setGiftNumber(Double.valueOf(memberGiftRecord.getCouponNumber()));
@@ -3175,22 +3351,22 @@
                    orderMoneyValue[i] = BigDecimal.ZERO;
                }
            }*/
            List<MgtMapTotalPlusVo> mgtMapTotalPlusVoList =  orderMapper.listMerOrderDistributionTotal(merTotalDto);
            if(mgtMapTotalPlusVoList!=null&&!mgtMapTotalPlusVoList.isEmpty()) {
                String[] orderTotalKey = new String[mgtMapTotalPlusVoList.size()];
                Integer[] orderTotalValue = new Integer[mgtMapTotalPlusVoList.size()];
                BigDecimal[] orderMoneyValue = new BigDecimal[mgtMapTotalPlusVoList.size()];
                MgtMapTotalPlusVo mgtMapTotalPlusVo;
                for (int i = 0; i < mgtMapTotalPlusVoList.size(); i++) {
                    mgtMapTotalPlusVo = mgtMapTotalPlusVoList.get(i);
                    orderTotalKey[i] = mgtMapTotalPlusVo.getMapKey();
                    orderTotalValue[i] = mgtMapTotalPlusVo.getMapValueFirst();
                    orderMoneyValue[i] = mgtMapTotalPlusVo.getMapValueSecond();
                }
                orderDistributionTotalVo.setOrderTotalKey(orderTotalKey);
                orderDistributionTotalVo.setOrderTotalValue(orderTotalValue);
                orderDistributionTotalVo.setOrderMoneyValue(orderMoneyValue);
        List<MgtMapTotalPlusVo> mgtMapTotalPlusVoList = orderMapper.listMerOrderDistributionTotal(merTotalDto);
        if (mgtMapTotalPlusVoList != null && !mgtMapTotalPlusVoList.isEmpty()) {
            String[] orderTotalKey = new String[mgtMapTotalPlusVoList.size()];
            Integer[] orderTotalValue = new Integer[mgtMapTotalPlusVoList.size()];
            BigDecimal[] orderMoneyValue = new BigDecimal[mgtMapTotalPlusVoList.size()];
            MgtMapTotalPlusVo mgtMapTotalPlusVo;
            for (int i = 0; i < mgtMapTotalPlusVoList.size(); i++) {
                mgtMapTotalPlusVo = mgtMapTotalPlusVoList.get(i);
                orderTotalKey[i] = mgtMapTotalPlusVo.getMapKey();
                orderTotalValue[i] = mgtMapTotalPlusVo.getMapValueFirst();
                orderMoneyValue[i] = mgtMapTotalPlusVo.getMapValueSecond();
            }
            orderDistributionTotalVo.setOrderTotalKey(orderTotalKey);
            orderDistributionTotalVo.setOrderTotalValue(orderTotalValue);
            orderDistributionTotalVo.setOrderMoneyValue(orderMoneyValue);
        }
        // 返回订单分布总数对象
        return orderDistributionTotalVo;
    }
@@ -3295,20 +3471,20 @@
    }
    /**
     * @description  商户端订单管理统计
     * @author  jqs
     * @date    2023/7/31 10:53
     * @param merOrderPageDto
     * @return  MerTotalOrderVo
     * @return MerTotalOrderVo
     * @description 商户端订单管理统计
     * @author jqs
     * @date 2023/7/31 10:53
     */
    @Override
    public MerTotalOrderVo totalMerOrder(MerOrderPageDto merOrderPageDto) {
        MerTotalOrderVo merTotalOrderVo = new MerTotalOrderVo();
        if(StringUtils.isNotBlank(merOrderPageDto.getKeyword())){
        if (StringUtils.isNotBlank(merOrderPageDto.getKeyword())) {
            MgtUserIdByKeywordDto userIdByKeywordDto = new MgtUserIdByKeywordDto();
            userIdByKeywordDto.setKeyword(merOrderPageDto.getKeyword());
            MgtUserIdByKeywordVo userIdByKeywordVo = remoteMemberService.getUserIdByKeyword(userIdByKeywordDto).getData();
            if(StringUtils.isNotBlank(userIdByKeywordVo.getUserIds())){
            if (StringUtils.isNotBlank(userIdByKeywordVo.getUserIds())) {
                List<Long> userIdList = Arrays.stream(userIdByKeywordVo.getUserIds().split(","))
                        .map(Long::parseLong)
                        .collect(Collectors.toList());
@@ -3379,33 +3555,33 @@
    }
    /**
     * @description 自动取消订单
     * @author  jqs
     * @date    2023/7/13 17:15
     * @param orderId
     * @return  void
     * @return void
     * @description 自动取消订单
     * @author jqs
     * @date 2023/7/13 17:15
     */
    @Override
    @Transactional
    public void autoCancelOrder(String orderId){
    public void autoCancelOrder(String orderId) {
        //更新订单信息
        Order order = this.getById(orderId);
        order.setOrderStatus(0);
        order.setCancelTime(new Date());
        this.saveOrUpdate(order);
        //活动订单回退库存
        if(order.getOrderFrom()==2){
        if (order.getOrderFrom() == 2) {
            List<OrderGoods> orderGoodsList = orderGoodsService.listByOrderId(orderId);
            if(orderGoodsList!=null&&!orderGoodsList.isEmpty()){
                for(OrderGoods orderGoods : orderGoodsList){
            if (orderGoodsList != null && !orderGoodsList.isEmpty()) {
                for (OrderGoods orderGoods : orderGoodsList) {
                    //redis库存控制极简版
                    String goodsLock = "goods_lock_"+order.getActivityId()+"_"+orderGoods.getGoodsId();
                    String goodsLock = "goods_lock_" + order.getActivityId() + "_" + orderGoods.getGoodsId();
                    RLock redissonLock = redissonClient.getLock(goodsLock);
                    try{
                    try {
                        redissonLock.lock(30, TimeUnit.SECONDS);
                        Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+order.getActivityId()+"-"+orderGoods.getGoodsId());
                        redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+order.getActivityId()+"-"+orderGoods.getGoodsId(),surpNum+orderGoods.getBuyNum());
                    }finally{
                        Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + order.getActivityId() + "-" + orderGoods.getGoodsId());
                        redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + order.getActivityId() + "-" + orderGoods.getGoodsId(), surpNum + orderGoods.getBuyNum());
                    } finally {
                        redissonLock.unlock();
                    }
                    //改变活动库存
@@ -3426,16 +3602,16 @@
                    remoteActivityService.delActivityRecord(activityRecord);
                }
            }
        }else{
            if(order.getCouponMoney().compareTo(BigDecimal.ZERO)>0){
        } else {
            if (order.getCouponMoney().compareTo(BigDecimal.ZERO) > 0) {
                //回退优惠券
                List<OrderGoods> orderGoodsList = orderGoodsService.listByOrderId(orderId);
                if(orderGoodsList!=null&&!orderGoodsList.isEmpty()) {
                if (orderGoodsList != null && !orderGoodsList.isEmpty()) {
                    StringJoiner memberCouponSJ = new StringJoiner(",");
                    for (OrderGoods orderGoods : orderGoodsList) {
                        memberCouponSJ.add(orderGoods.getCouponId());
                    }
                    if(memberCouponSJ!=null){
                    if (memberCouponSJ != null) {
                        remoteCouponService.backMemberCoupon(memberCouponSJ.toString());
                    }
@@ -3445,17 +3621,17 @@
    }
    /**
     * @description  订单支付回调
     * @author  jqs
     * @date    2023/7/13 17:57
     * @param transaction
     * @return  void
     * @return void
     * @description 订单支付回调
     * @author jqs
     * @date 2023/7/13 17:57
     */
    @Override
    @Transactional
    public void payBack(Transaction transaction) {
    public void payBack(PartnerTransactionsResult transaction) {
        // 更新订单状态
        String orderId=transaction.getOutTradeNo();
        String orderId = transaction.getOutTradeNo();
        Order order = this.getById(orderId);
        order.setOrderStatus(2);
        order.setPayTime(new Date());
@@ -3501,8 +3677,8 @@
            goodsTotalChangeDto.setChangeType(1);
            goodsTotalChangeDto.setChangeNum(orderGoods.getBuyNum());
            goodsTotalChangeDto.setMoney(orderGoods.getGoodsReceivableMoney());
            Integer bugGoodsNum = orderMapper.countUserBuyGoodsNum(order.getUserId(),orderGoods.getGoodsId());
            if(bugGoodsNum==null||bugGoodsNum<1){
            Integer bugGoodsNum = orderMapper.countUserBuyGoodsNum(order.getUserId(), orderGoods.getGoodsId());
            if (bugGoodsNum == null || bugGoodsNum < 1) {
                goodsTotalChangeDto.setPersonNum(1);
            }
            goodsTotalChangeDtoList.add(goodsTotalChangeDto);
@@ -3586,16 +3762,16 @@
    }
    /**
     * @description  订单退款
     * @author  jqs
     * @date    2023/7/13 18:36
     * @param orderId
     * @return  void
     * @return void
     * @description 订单退款
     * @author jqs
     * @date 2023/7/13 18:36
     */
    @Override
    @Transactional
    public void refundOrder(String orderId){
        //更新订单信息
    public void refundOrder(String orderId) {
        // 更新订单信息
        Order order = this.getById(orderId);
        order.setOrderStatus(0);
        order.setCancelTime(new Date());
@@ -3608,7 +3784,7 @@
        orderRefund.setOrderId(order.getOrderId());
        orderRefund.setUserId(order.getUserId());
        orderRefund.setShopId(order.getShopId());
        orderRefund.setRefundMoney(order.getPayMoney());
        orderRefund.setRefundMoney(order.getOnlinePayMoney());
        orderRefund.setOrderMoney(order.getPayMoney());
        orderRefund.setCreateTime(new Date());
        // 初始化各类商品的收款金额
@@ -3622,19 +3798,19 @@
        Boolean haveExperience = false;
        Boolean haveGoods = false;
        List<OrderGoods> orderGoodsList = orderGoodsService.listByOrderId(orderId);
        if(orderGoodsList!=null&&!orderGoodsList.isEmpty()){
        if (orderGoodsList != null && !orderGoodsList.isEmpty()) {
            StringJoiner memberCouponSJ = new StringJoiner(",");
            for(OrderGoods orderGoods : orderGoodsList){
                if(order.getOrderFrom()==2){
            for (OrderGoods orderGoods : orderGoodsList) {
                if (order.getOrderFrom() == 2) {
                    //redis库存控制极简版
                    //活动订单回退库存
                    String goodsLock = "goods_lock_"+order.getActivityId()+"_"+orderGoods.getGoodsId();
                    String goodsLock = "goods_lock_" + order.getActivityId() + "_" + orderGoods.getGoodsId();
                    RLock redissonLock = redissonClient.getLock(goodsLock);
                    try{
                    try {
                        redissonLock.lock(30, TimeUnit.SECONDS);
                        Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+order.getActivityId()+"-"+orderGoods.getGoodsId());
                        redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+order.getActivityId()+"-"+orderGoods.getGoodsId(),surpNum+orderGoods.getBuyNum());
                    }finally{
                        Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + order.getActivityId() + "-" + orderGoods.getGoodsId());
                        redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + order.getActivityId() + "-" + orderGoods.getGoodsId(), surpNum + orderGoods.getBuyNum());
                    } finally {
                        redissonLock.unlock();
                    }
                    //改变活动库存
@@ -3653,7 +3829,7 @@
                    activityRecord.setUserId(order.getUserId());
                    activityRecord.setOrderTime(order.getCreateTime());
                    remoteActivityService.delActivityRecord(activityRecord);
                }else{
                } else {
                    memberCouponSJ.add(orderGoods.getCouponId());
                }
                switch (orderGoods.getGoodsType()) {
@@ -3678,7 +3854,7 @@
                }
            }
            //回退优惠券
            if(memberCouponSJ!=null){
            if (memberCouponSJ != null) {
                remoteCouponService.backMemberCoupon(memberCouponSJ.toString());
            }
        }
@@ -3737,43 +3913,97 @@
            activityTotalChangeDto.setUserId(order.getUserId());
            remoteActivityService.changeActivityTotal(activityTotalChangeDto);
        }
        // 用户取消订单退款
        BigDecimal onlinePayMoney = order.getOnlinePayMoney();
        if(BigDecimal.ZERO.compareTo(onlinePayMoney) < 0){
            // 订单支付金额大于0,可发起退款
            orderWxApplyRefund(orderId, refundId, onlinePayMoney, orderRefund);
        }
        orderRefund.setRefundStatus(1);
        orderRefundService.saveOrUpdate(orderRefund);
    }
    /**
     * @description  员工端活动订单统计
     * @author  jqs
     * @date    2023/7/17 15:25
     * 申请退款API
     */
    private void orderWxApplyRefund(String orderId, String outRefundNo, BigDecimal payMoney, OrderRefund orderRefund){
        try {
            // 创建支付订单
            OrderPayment orderPayment = orderPaymentService.getByOrderId(orderId);
            if (null == orderPayment) {
                return;
            }
            String subMchId = orderPayment.getSubMchId();
            WxPayConfig config = wxService.getConfig();
            RefundsRequest request = new RefundsRequest();
            request.setSpAppid(config.getAppId());
            request.setSubMchid(subMchId);
            request.setTransactionId(orderPayment.getTransactionId());
            request.setOutRefundNo(outRefundNo);
            request.setReason("用户取消订单");
            // 订单金额
            int total = payMoney.multiply(new BigDecimal(100)).intValue();
            RefundsRequest.Amount amount = RefundsRequest.Amount.builder().refund(total).total(total).currency("CNY").build();
            request.setAmount(amount);
            request.setNotifyUrl(config.getNotifyUrl());
            RefundsResult result = wxService.getEcommerceService().refunds(request);
            // 微信退款id
            orderRefund.setWxRefundId(result.getRefundId());
            // 请求参数
            Gson gson = new Gson();
            String refundRequestJson = gson.toJson(request);
            // 返回参数
            String refundResponseJson = gson.toJson(result);
            // 保存支付订单统一下单日志
            paymentMessageService.savePaymentMessage("3", orderId, refundRequestJson, refundResponseJson);
        } catch (WxPayException e) {
            throw new ServiceException(e.getMessage());
        }
    }
    /**
     * @param staffTotalDto
     * @return  StaffActivityOrderTotalVo
     * @return StaffActivityOrderTotalVo
     * @description 员工端活动订单统计
     * @author jqs
     * @date 2023/7/17 15:25
     */
    @Override
    public StaffActivityOrderTotalVo getStaffActivityOrderTotal(StaffTotalDto staffTotalDto){
    public StaffActivityOrderTotalVo getStaffActivityOrderTotal(StaffTotalDto staffTotalDto) {
        StaffActivityOrderTotalVo staffActivityOrderTotalVo = orderMapper.getStaffActivityOrderTotal(staffTotalDto);
        return staffActivityOrderTotalVo;
    }
    /**
     * @description  员工端活动统计
     * @author  jqs
     * @date    2023/7/17 15:51
     * @param staffTotalDto
     * @return  StaffActivityTotalVo
     * @return StaffActivityTotalVo
     * @description 员工端活动统计
     * @author jqs
     * @date 2023/7/17 15:51
     */
    @Override
    public StaffActivityTotalVo getStaffActivityTotal(StaffTotalDto staffTotalDto){
    public StaffActivityTotalVo getStaffActivityTotal(StaffTotalDto staffTotalDto) {
        StaffActivityTotalVo staffActivityTotalVo = orderMapper.getStaffActivityTotal(staffTotalDto);
        return staffActivityTotalVo;
    }
    /**
     * @description  员工端活动统计订单分布
     * @author  jqs
     * @date    2023/7/17 16:16
     * @param staffTotalDto
     * @return  MerOrderDistributionTotalVo
     * @return MerOrderDistributionTotalVo
     * @description 员工端活动统计订单分布
     * @author jqs
     * @date 2023/7/17 16:16
     */
    @Override
    public MerOrderDistributionTotalVo getStaffOrderDistributionTotal(StaffTotalDto staffTotalDto){
    public MerOrderDistributionTotalVo getStaffOrderDistributionTotal(StaffTotalDto staffTotalDto) {
        MerOrderDistributionTotalVo orderDistributionTotalVo = new MerOrderDistributionTotalVo();
        // 获取订单年龄用户列表
        MerTotalDto merTotalDto = new MerTotalDto();
@@ -3814,7 +4044,7 @@
                }
                // 如果用户ID列表不为空
                if (userIdList != null && !userIdList.isEmpty()) {
                    mgtMapTotalPlusVo = orderMapper.listStaffActivityOrderDistributionTotal(userIdList,staffTotalDto.getShopId(),staffTotalDto.getActivityId());
                    mgtMapTotalPlusVo = orderMapper.listStaffActivityOrderDistributionTotal(userIdList, staffTotalDto.getShopId(), staffTotalDto.getActivityId());
                    orderTotalValue[i] = mgtMapTotalPlusVo.getMapValueFirst();
                    orderMoneyValue[i] = mgtMapTotalPlusVo.getMapValueSecond();
                } else {
@@ -3833,14 +4063,14 @@
    /**
     * @description  员工端活动统计销售占比
     * @author  jqs
     * @date    2023/7/17 17:03
     * @param staffTotalDto
     * @return  MerOrderTypeTotalVo
     * @return MerOrderTypeTotalVo
     * @description 员工端活动统计销售占比
     * @author jqs
     * @date 2023/7/17 17:03
     */
    @Override
    public MerOrderTypeTotalVo getStaffOrderTypeTotal(StaffTotalDto staffTotalDto){
    public MerOrderTypeTotalVo getStaffOrderTypeTotal(StaffTotalDto staffTotalDto) {
        MerOrderTypeTotalVo orderTypeTotalVo = new MerOrderTypeTotalVo();
        //获取商品分类销售数据
        List<MgtMapTotalPlusVo> MgtMapIntTotalVoGoodsType = orderMapper.listStaffOrderTotalGoodsType(staffTotalDto);
@@ -3878,11 +4108,11 @@
    }
    /**
     * @description  员工端获客人数
     * @author  jqs
     * @date    2023/7/17 18:42
     * @param staffTotalDto
     * @return  StaffActivityDateMemberTotalVo
     * @return StaffActivityDateMemberTotalVo
     * @description 员工端获客人数
     * @author jqs
     * @date 2023/7/17 18:42
     */
    @Override
    public StaffActivityDateMemberTotalVo getStaffActivityGetMemberTotal(StaffTotalDto staffTotalDto) {
@@ -3919,11 +4149,11 @@
    }
    /**
     * @description  员工端获客人数
     * @author  jqs
     * @date    2023/7/17 18:42
     * @param staffTotalDto
     * @return  StaffActivityDateMemberTotalVo
     * @return StaffActivityDateMemberTotalVo
     * @description 员工端获客人数
     * @author jqs
     * @date 2023/7/17 18:42
     */
    @Override
    public StaffActivityDateMemberTotalVo getStaffActivityMemberTotal(StaffTotalDto staffTotalDto) {
@@ -3960,12 +4190,12 @@
    }
    /**
     * @description  获取时间段日期
     * @author  jqs
     * @date    2023/7/17 19:11
     * @param startDate
     * @param endDate
     * @return  List<String>
     * @return List<String>
     * @description 获取时间段日期
     * @author jqs
     * @date 2023/7/17 19:11
     */
    public static List<String> getDateRange(String startDate, String endDate) {
        List<String> dateList = new ArrayList<>();
@@ -3979,50 +4209,87 @@
    }
    /**
     * @description  检查订单状态定时任务
     * @author  jqs
     * @date    2023/7/25 14:40
     * @param
     * @return  void
     * @return void
     * @description 检查订单状态定时任务
     * @author jqs
     * @date 2023/7/25 14:40
     */
    @Override
    public void checkOrderStatus(){
    public void checkOrderStatus() {
        Integer delayTime = 30;
        if(redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)){
        if (redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)) {
            delayTime = redisService.getCacheObject(SecurityConstant.AUTO_CANCEL_ORDER_TIME);
        }
        delayTime = delayTime + 5;
        Date checkTime = DateUtils.addMinutes(new Date(),-delayTime);
        Date checkTime = DateUtils.addMinutes(new Date(), -delayTime);
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Order::getDelFlag,0);
        queryWrapper.lt(Order::getCreateTime,checkTime);
        queryWrapper.eq(Order::getOrderStatus,1);
        queryWrapper.eq(Order::getDelFlag, 0);
        queryWrapper.lt(Order::getCreateTime, checkTime);
        queryWrapper.eq(Order::getOrderStatus, 1);
        List<Order> orderList = this.list(queryWrapper);
        if(orderList!=null&&!orderList.isEmpty()){
            for(Order order: orderList){
        if (orderList != null && !orderList.isEmpty()) {
            for (Order order : orderList) {
                autoTimeCancelOrder(order);
            }
        }
    }
    private void autoTimeCancelOrder(Order order){
    @Override
    public void profitSharingBack(ProfitSharingNotifyResult result) {
        try {
            String outOrderNo = result.getOutOrderNo();
            ProfitSharing profitSharing = profitSharingService.getById(outOrderNo);
            if(null != profitSharing){
                profitSharing.setWxOrderId(result.getOrderId());
                profitSharing.setFinishTime(result.getSuccessTime());
                profitSharing.setFinishFlag(1);
                profitSharingService.saveOrUpdate(profitSharing);
            }
        } catch (Exception e){
            log.error("==分账回成功回调操作====【{}】========={}", result.getOutOrderNo(), e.getMessage());
        }
    }
    @Override
    public void orderRefundBack(RefundNotifyResult result) {
        try {
            String outRefundNo = result.getOutRefundNo();
            String refundStatus = result.getRefundStatus();
            OrderRefund orderRefund = orderRefundService.getById(outRefundNo);
            if(null != orderRefund){
                orderRefund.setWxRefundId(result.getRefundId());
                orderRefund.setBackTime(result.getSuccessTime());
                orderRefund.setRefundStatus(IDict.getCodeByText(RefundStatusEnum.class, refundStatus));
                orderRefundService.saveOrUpdate(orderRefund);
            }
        } catch (Exception e){
            log.error("==退款回成功回调操作====【{}】========={}", result.getOutRefundNo(), e.getMessage());
        }
    }
    private void autoTimeCancelOrder(Order order) {
        String orderId = order.getOrderId();
        order.setOrderStatus(0);
        order.setCancelTime(new Date());
        this.saveOrUpdate(order);
        //活动订单回退库存
        if(order.getOrderFrom()==2){
        if (order.getOrderFrom() == 2) {
            List<OrderGoods> orderGoodsList = orderGoodsService.listByOrderId(orderId);
            if(orderGoodsList!=null&&!orderGoodsList.isEmpty()){
                for(OrderGoods orderGoods : orderGoodsList){
            if (orderGoodsList != null && !orderGoodsList.isEmpty()) {
                for (OrderGoods orderGoods : orderGoodsList) {
                    //redis库存控制极简版
                    String goodsLock = "goods_lock_"+order.getActivityId()+"_"+orderGoods.getGoodsId();
                    String goodsLock = "goods_lock_" + order.getActivityId() + "_" + orderGoods.getGoodsId();
                    RLock redissonLock = redissonClient.getLock(goodsLock);
                    try{
                    try {
                        redissonLock.lock(30, TimeUnit.SECONDS);
                        Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+order.getActivityId()+"-"+orderGoods.getGoodsId());
                        redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+order.getActivityId()+"-"+orderGoods.getGoodsId(),surpNum+orderGoods.getBuyNum());
                    }finally{
                        Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + order.getActivityId() + "-" + orderGoods.getGoodsId());
                        redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + order.getActivityId() + "-" + orderGoods.getGoodsId(), surpNum + orderGoods.getBuyNum());
                    } finally {
                        redissonLock.unlock();
                    }
                    //改变活动库存
@@ -4043,16 +4310,16 @@
                    remoteActivityService.delActivityRecord(activityRecord);
                }
            }
        }else{
            if(order.getCouponMoney().compareTo(BigDecimal.ZERO)>0){
        } else {
            if (order.getCouponMoney().compareTo(BigDecimal.ZERO) > 0) {
                //回退优惠券
                List<OrderGoods> orderGoodsList = orderGoodsService.listByOrderId(orderId);
                if(orderGoodsList!=null&&!orderGoodsList.isEmpty()) {
                if (orderGoodsList != null && !orderGoodsList.isEmpty()) {
                    StringJoiner memberCouponSJ = new StringJoiner(",");
                    for (OrderGoods orderGoods : orderGoodsList) {
                        memberCouponSJ.add(orderGoods.getCouponId());
                    }
                    if(memberCouponSJ!=null){
                    if (memberCouponSJ != null) {
                        remoteCouponService.backMemberCoupon(memberCouponSJ.toString());
                    }
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/order/OrderService.java
@@ -2,6 +2,9 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.github.binarywang.wxpay.bean.ecommerce.PartnerTransactionsResult;
import com.github.binarywang.wxpay.bean.ecommerce.RefundNotifyResult;
import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyResult;
import com.ruoyi.order.domain.dto.*;
import com.ruoyi.order.domain.pojo.order.Order;
import com.ruoyi.order.domain.vo.*;
@@ -416,7 +419,7 @@
     * @param Transaction transaction
     * @return  void
     */
    void payBack(Transaction transaction);
    void payBack(PartnerTransactionsResult transaction);
    /**
     * 取消订单
@@ -491,6 +494,18 @@
    void checkOrderStatus();
    /**
     * 分账通知回调
     * @param result
     */
    void profitSharingBack(ProfitSharingNotifyResult result);
    /**
     * 订单退款回调
     * @param result
     */
    void orderRefundBack(RefundNotifyResult result);
    /**
     * @description  获取商户订单统计
     * @author  jqs
     * @date    2023/8/4 10:25
ruoyi-modules/ruoyi-order/src/main/resources/bootstrap.yml
@@ -3,7 +3,7 @@
  port: 10064
# Spring
spring:
spring:
  application:
    # 应用名称
    name: ruoyi-order
@@ -25,3 +25,13 @@
        # 共享配置
        shared-configs:
          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
wx:
  pay:
    appId: #微信公众号或者小程序等的appid(平台)
    mchId: #微信支付商户号(平台)
    mchKey: #微信支付商户密钥(平台)
    platformTyMacId: # 平台特约商户号,用户平台收取服务费
    subAppId: #服务商模式下的子商户公众账号ID (这个可以不用配置)
    subMchId: #服务商模式下的子商户号 (二级商户号  也不用配置)
    keyPath: # (商户平台 下载的V3证书)p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/controller/console/ShopController.java
@@ -2,6 +2,9 @@
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.bean.BeanUtils;
import com.ruoyi.shop.domain.pojo.shop.ShopAuthentication;
import com.ruoyi.shop.domain.pojo.shop.ShopProportion;
import com.ruoyi.shop.domain.pojo.shop.ShopRelUser;
import com.ruoyi.shop.domain.pojo.shop.ShopStaff;
import com.ruoyi.shop.service.shop.*;
@@ -10,6 +13,7 @@
import com.ruoyi.system.api.constant.AppErrorConstant;
import com.ruoyi.system.api.domain.dto.*;
import com.ruoyi.system.api.domain.poji.shop.Shop;
import com.ruoyi.system.api.domain.poji.shop.ShopProportionVo;
import com.ruoyi.system.api.domain.poji.sys.SysUser;
import com.ruoyi.system.api.domain.vo.*;
import com.ruoyi.system.api.model.QwH5LoginVo;
@@ -59,6 +63,12 @@
    @Resource
    private MemberTaskService memberTaskService;
    @Resource
    private ShopAuthenticationService shopAuthenticationService;
    @Resource
    private ShopProportionService shopProportionService;
    /**
     * 企业微信H5登录
     * @param qwUserDetail
@@ -90,6 +100,30 @@
        return R.ok(shop);
    }
    @PostMapping("/getShopSubMchId")
    public R<String> getShopSubMchId(@RequestBody Long shopId){
        String subMchid = "";
        ShopAuthentication authentication = shopAuthenticationService.getByShopId(shopId);
        if(null != authentication){
            subMchid = authentication.getSubMchid();
        }
        return R.ok(subMchid, "");
    }
    /**
     * 获取商户分成
     * @param shopId
     * @return
     */
    @PostMapping("/getShopProportion")
    public R<ShopProportionVo> getShopProportion(@RequestBody Long shopId){
        ShopProportion shopProportion = shopProportionService.getByShopId(shopId);
        ShopProportionVo shopProportionVo = new ShopProportionVo();
        BeanUtils.copyBeanProp(shopProportionVo, shopProportion);
        return R.ok(shopProportionVo);
    }
    @PostMapping("/getShopByUserId")
    public R<ShopRelUserVo> getShopByUserId(@RequestBody Long userId)
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/enums/WxApplyMentSignStateEnum.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.shop.enums;
import com.ruoyi.shop.enums.dict.IDict;
public enum WxApplyMentSignStateEnum implements IDict<Integer> {
    /**
     * 签约状态
         1、UNSIGNED:未签约。该状态下,电商平台可查询获取签约链接,引导二级商户的超级管理员完成签约;
         2、SIGNED :已签约。指二级商户的超级管理员已完成签约。注意:若申请单被驳回,商户修改了商户主体名称、法人名称、超级管理员信息、主体类型等信息,则需重新签约。
         3、NOT_SIGNABLE:不可签约。该状态下,暂不支持超级管理员签约。一般为申请单处于已驳回、已冻结、机器校验中状态,无法签约。
     */
    UNSIGNED(1, "UNSIGNED"),
    SIGNED(2, "SIGNED"),
    NOT_SIGNABLE(3, "NOT_SIGNABLE");
    WxApplyMentSignStateEnum(Integer code, String text){
        init(code, text);
    }
}
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/enums/WxApplyMentStateEnum.java
New file
@@ -0,0 +1,30 @@
package com.ruoyi.shop.enums;
import com.ruoyi.shop.enums.dict.IDict;
public enum WxApplyMentStateEnum implements IDict<Integer> {
    /**
     * 审核状态
        1:CHECKING:资料校验中
        2:ACCOUNT_NEED_VERIFY:待账户验证
        3:AUDITING:审核中
        4:REJECTED:已驳回
        5:NEED_SIGN:待签约
        6:FINISH:完成
        7:FROZEN:已冻结
        8:CANCELED:已作废
     */
    CHECKING(1, "CHECKING"),
    ACCOUNT_NEED_VERIFY(2, "ACCOUNT_NEED_VERIFY"),
    AUDITING(3, "AUDITING"),
    REJECTED(4, "REJECTED"),
    NEED_SIGN(5, "NEED_SIGN"),
    FINISH(6, "FINISH"),
    FROZEN(7, "FROZEN"),
    CANCELED(8, "CANCELED");
    WxApplyMentStateEnum(Integer code, String text){
        init(code, text);
    }
}
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/enums/dict/DictBean.java
New file
@@ -0,0 +1,15 @@
package com.ruoyi.shop.enums.dict;
import lombok.Data;
/**
 * 字典bean
 * 只有code和text,可用于展示下拉框
 *
 * @author luozhan
 */
@Data
public class DictBean<T> implements IDict<T> {
    private final T code;
    private final String text;
}
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/enums/dict/IDict.java
New file
@@ -0,0 +1,170 @@
package com.ruoyi.shop.enums.dict;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
 * 字典接口
 * <p>
 * 自定义的字典枚举类实现本接口后可省略属性code和text,以及对应的get方法
 * 在构造方法中只需调用init方法即可初始化
 *
 * @author luozhan
 * @date 2021-12
 */
public interface IDict<T> {
    /**
     * 通过code获取value
     *
     * @param clazz 枚举class
     * @param code  code
     * @return text
     */
    static <T> String getTextByCode(Class<? extends IDict<T>> clazz, T code) {
        return Stream.of(clazz.getEnumConstants())
                .filter((IDict<T> e) -> e.getCode().equals(code))
                .map(IDict::getText)
                .findAny().orElse("");
    }
    /**
     * 通过text获取code
     *
     * @param clazz 枚举class
     * @param text  text
     * @return code
     */
    static <T> T getCodeByText(Class<? extends IDict<T>> clazz, String text) {
        return Stream.of(clazz.getEnumConstants())
                .filter((IDict<T> e) -> e.getText().equals(text))
                .map(IDict::getCode)
                .findAny().orElse(null);
    }
    /**
     * 通过code获取字典枚举实例
     *
     * @param clazz 枚举class
     * @param code  code
     * @param <T>   字典code类型
     * @param <R>   枚举类型
     * @return 字典枚举实例
     */
    @SuppressWarnings("unchecked")
    static <T, R extends IDict<T>> R getByCode(Class<? extends IDict<T>> clazz, T code) {
        return Stream.of(clazz.getEnumConstants())
                .filter((IDict<T> e) -> (e.getCode().equals(code)))
                .map(v -> (R) v)
                .findAny()
                .orElse(null);
    }
    /**
     * 获取给定的字典枚举项(常用下拉框数据请求)
     *
     * @param enums 可指定需要哪些项
     * @return List
     */
    @SafeVarargs
    static <T, E extends IDict<T>> List<IDict<T>> getItems(E... enums) {
        return Stream.of(enums)
                .map(DictPool::getDict)
                .collect(Collectors.toList());
    }
    /**
     * 获取所有字典枚举项,除开指定的枚举
     *
     * @param exclude 指定排除的枚举
     * @return List
     */
    @SafeVarargs
    @SuppressWarnings("unchecked")
    static <T, E extends IDict<T>> List<IDict<T>> getItemsExclude(E... exclude) {
        Class<IDict<T>> clazz = (Class<IDict<T>>) exclude.getClass().getComponentType();
        IDict<T>[] allEnum = clazz.getEnumConstants();
        List<IDict<T>> excludeList = Arrays.asList(exclude);
        return Stream.of(allEnum)
                .filter(e -> !excludeList.contains(e))
                .map(DictPool::getDict)
                .collect(Collectors.toList());
    }
    /**
     * 获取所有字典枚举项(常用下拉框数据请求)
     * 枚举值上标记@Deprecated的不会返回
     *
     * @param clazz 字典枚举类
     * @return List
     */
    static <T> List<IDict<T>> getAll(Class<? extends IDict<T>> clazz) {
        Map<String, Field> fieldCache = Arrays.stream(clazz.getDeclaredFields()).
                filter(Field::isEnumConstant).
                collect(Collectors.toMap(Field::getName, Function.identity()));
        IDict<T>[] allEnum = clazz.getEnumConstants();
        return Stream.of(allEnum)
                .filter(e -> !fieldCache.get(((Enum<?>) e).name()).isAnnotationPresent(Deprecated.class))
                .map(DictPool::getDict)
                .collect(Collectors.toList());
    }
    /**
     * 初始化
     *
     * @param code 字典编码
     * @param text 字典文本
     */
    default void init(T code, String text) {
        DictPool.putDict(this, code, text);
    }
    /**
     * 获取编码
     *
     * @return 编码
     */
    default T getCode() {
        return DictPool.getDict(this).getCode();
    }
    /**
     * 获取文本
     *
     * @return 文本
     */
    default String getText() {
        return DictPool.getDict(this).getText();
    }
    @SuppressWarnings("all")
    class DictPool {
        private static final Map<IDict, DictBean> DICT_MAP = new ConcurrentHashMap<>();
        private static final Map<String, Class<? extends IDict>> DICT_NAME_CLASS_MAP = new ConcurrentHashMap<>();
        static <T> void putDict(IDict<T> dict, T code, String text) {
            DICT_NAME_CLASS_MAP.put(dict.getClass().getName(), dict.getClass());
            DICT_MAP.put(dict, new DictBean<>(code, text));
        }
        public static List<IDict<Object>> getDict(String dictName) {
            Class<? extends IDict> aClass = DICT_NAME_CLASS_MAP.get(dictName);
            return IDict.getAll((Class<? extends IDict<Object>>) aClass);
        }
        static <K extends IDict<T>, T> DictBean<T> getDict(K dict) {
            return DICT_MAP.get(dict);
        }
    }
}
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/scheduler/ShopScheduler.java
@@ -1,7 +1,12 @@
package com.ruoyi.shop.scheduler;
import com.ruoyi.common.core.utils.bean.BeanUtils;
import com.ruoyi.common.core.utils.uuid.IdUtils;
import com.ruoyi.shop.domain.pojo.shop.ShopAuthentication;
import com.ruoyi.shop.service.shop.ShopService;
import com.ruoyi.shop.service.task.ShopTaskService;
import com.ruoyi.system.api.domain.poji.shop.Shop;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
@@ -21,6 +26,9 @@
    @Resource
    private ShopTaskService shopTaskService;
    @Resource
    private ShopService shopService;
    /**
     * 定时检查跟进任务状态
@@ -33,4 +41,16 @@
        }
    }
    /**
     * 0 0/1 * * * ?
     * 定时检查 每分钟检查一次 微信二级商户进件状态
     */
    @Scheduled(cron="0 0/1 * * * ?")
    private void queryEcommerceApplyMentsStatus(){
        if(schedulerUtils.getSchedulerRun()) {
            log.info("--------------------定时检查微信二级商户进件状态任务开始执行--------------------");
            shopService.queryEcommerceApplyMentsStatus();
            log.info("--------------------定时检查微信二级商户进件状态任务结束执行--------------------");
        }
    }
}
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/impl/shop/ShopAuthenticationServiceImpl.java
@@ -1,10 +1,23 @@
package com.ruoyi.shop.service.impl.shop;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsStatusResult;
import com.google.common.base.Joiner;
import com.ruoyi.shop.domain.pojo.shop.ShopAuthentication;
import com.ruoyi.shop.enums.WxApplyMentSignStateEnum;
import com.ruoyi.shop.enums.WxApplyMentStateEnum;
import com.ruoyi.shop.enums.dict.IDict;
import com.ruoyi.shop.mapper.shop.ShopAuthenticationMapper;
import com.ruoyi.shop.service.shop.ShopAuthenticationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
 * <p>
@@ -17,4 +30,72 @@
@Service
public class ShopAuthenticationServiceImpl extends ServiceImpl<ShopAuthenticationMapper, ShopAuthentication> implements ShopAuthenticationService {
    @Override
    public List<ShopAuthentication> getShopAuthNeedUpdateStatus() {
        List<Integer> auditStatusList = Arrays.asList(1, 2, 3, 5);
        LambdaQueryWrapper<ShopAuthentication> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(ShopAuthentication::getAuditStatus, auditStatusList);
        queryWrapper.isNotNull(ShopAuthentication::getApplymentId);
        return this.list(queryWrapper);
    }
    @Override
    public void updateAuditStatusByApplymentId(String applymentId, ApplymentsStatusResult result) {
        // WxApplyMentStateEnum
        String applymentState = result.getApplymentState();
        Integer auditStatus = IDict.getCodeByText(WxApplyMentStateEnum.class, applymentState);
        Integer signState = IDict.getCodeByText(WxApplyMentSignStateEnum.class, result.getSignState());
        LambdaUpdateWrapper<ShopAuthentication> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(ShopAuthentication::getApplymentId, applymentId)
                .set(ShopAuthentication::getAuditStatus, auditStatus)
                .set(ShopAuthentication::getSignState, signState);
        if(WxApplyMentStateEnum.ACCOUNT_NEED_VERIFY.getCode().equals(auditStatus)){
            // ACCOUNT_NEED_VERIFY 待账户验证
            updateWrapper.set(ShopAuthentication::getLegalValidationUrl, result.getLegalValidationUrl());
            ApplymentsStatusResult.AccountValidation accountValidation = result.getAccountValidation();
            if(null != accountValidation) {
                updateWrapper.set(ShopAuthentication::getAvAccountName, accountValidation.getAccountName())
                    .set(ShopAuthentication::getAvAccountNo, accountValidation.getAccountNo())
                    .set(ShopAuthentication::getAvPayAmount, accountValidation.getPayAmount())
                    .set(ShopAuthentication::getDaNumber, accountValidation.getDestinationAccountNumber())
                    .set(ShopAuthentication::getDaName, accountValidation.getDestinationAccountName())
                    .set(ShopAuthentication::getDaBank, accountValidation.getDestinationAccountBank())
                    .set(ShopAuthentication::getDaCity, accountValidation.getCity())
                    .set(ShopAuthentication::getDaRemark, accountValidation.getRemark())
                    .set(ShopAuthentication::getDaDeadline, accountValidation.getDeadline());
            }
        } else if(WxApplyMentStateEnum.NEED_SIGN.getCode().equals(auditStatus)){
            // NEED_SIGN 待签约
            updateWrapper.set(ShopAuthentication::getSignUrl, result.getSignUrl());
            updateWrapper.set(ShopAuthentication::getSubMchid, result.getSubMchid());
        } else if(WxApplyMentStateEnum.FINISH.getCode().equals(auditStatus)){
            // FINISH 完成
            updateWrapper.set(ShopAuthentication::getSubMchid, result.getSubMchid());
        } else if(WxApplyMentStateEnum.REJECTED.getCode().equals(auditStatus)
                || WxApplyMentStateEnum.FROZEN.getCode().equals(auditStatus)){
            List<ApplymentsStatusResult.AuditDetail> auditDetail = result.getAuditDetail();
            if(null != auditDetail && !auditDetail.isEmpty()){
                List<String> paramNameList = auditDetail.stream().map(ApplymentsStatusResult.AuditDetail::getParamName).collect(Collectors.toList());
                List<String> rejectReason = auditDetail.stream().map(ApplymentsStatusResult.AuditDetail::getRejectReason).collect(Collectors.toList());
                updateWrapper.set(ShopAuthentication::getAdParamName, Joiner.on(";").join(paramNameList))
                        .set(ShopAuthentication::getAdRejectReason, Joiner.on(";").join(rejectReason));
            }
        }
        this.update(updateWrapper);
    }
    @Override
    public ShopAuthentication getByShopId(Long shopId) {
        LambdaQueryWrapper<ShopAuthentication> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ShopAuthentication::getShopId, shopId)
                .last(" limit 1 ");
        return this.getOne(queryWrapper);
    }
}
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/impl/shop/ShopProportionServiceImpl.java
@@ -1,7 +1,10 @@
package com.ruoyi.shop.service.impl.shop;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.shop.domain.dto.MgtShopProportionEditDto;
import com.ruoyi.shop.domain.pojo.shop.ShopAuthentication;
import com.ruoyi.shop.domain.pojo.shop.ShopProportion;
import com.ruoyi.shop.mapper.shop.ShopProportionMapper;
import com.ruoyi.shop.service.shop.ShopProportionService;
@@ -48,4 +51,13 @@
        shopProportionNew.setUpdateUserId(mgtShopProportionEditDto.getUserId());
        this.saveOrUpdate(shopProportionNew);
    }
    @Override
    public ShopProportion getByShopId(Long shopId) {
        LambdaQueryWrapper<ShopProportion> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ShopProportion::getShopId, shopId)
                .eq(ShopProportion::getDelFlag, 0)
                .last(" limit 1 ");
        return this.getOne(queryWrapper);
    }
}
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/impl/shop/ShopServiceImpl.java
@@ -2,9 +2,12 @@
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsResult;
import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsStatusResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.exception.ServiceException;
@@ -18,11 +21,15 @@
import com.ruoyi.shop.domain.pojo.shop.*;
import com.ruoyi.shop.domain.pojo.task.ShopFile;
import com.ruoyi.shop.domain.vo.*;
import com.ruoyi.shop.enums.WxApplyMentStateEnum;
import com.ruoyi.shop.mapper.shop.ShopMapper;
import com.ruoyi.shop.service.shop.*;
import com.ruoyi.shop.service.task.MemberTaskService;
import com.ruoyi.shop.service.task.ShopFileService;
import com.ruoyi.shop.service.task.ShopTaskService;
import com.ruoyi.shop.util.WechatPayUtils;
import com.ruoyi.shop.util.WxShopUtils;
import com.ruoyi.shop.util.dto.*;
import com.ruoyi.system.api.constant.AppErrorConstant;
import com.ruoyi.system.api.domain.dto.*;
import com.ruoyi.system.api.domain.poji.config.SysTag;
@@ -115,11 +122,12 @@
    @Resource
    private RedisService redisService;
    /*@Resource
    private WechatPayUtils wechatPayUtils;*/
    @Resource
    private WechatPayUtils wechatPayUtils;
    /**
     * 获取商户详情
     *
     * @param shopId
     * @return
     */
@@ -968,7 +976,7 @@
        shopAuthentication.setApplyNumber(applyNumber);
        shopAuthentication.setAuditStatus(3);
        shopAuthenticationService.saveOrUpdate(shopAuthentication);
        //wechatPayUtils.ecommerceApply(shopAuthentication,applyNumber,shop);
        wechatPayUtils.ecommerceApply(shopAuthentication,applyNumber,shop);
    }
    /**
@@ -1336,4 +1344,44 @@
        shop.setUpdateTime(new Date());
        shopMapper.updateShop(shop);
    }
    @Override
    public void queryEcommerceApplyMentsStatus() {
        List<ShopAuthentication> list = shopAuthenticationService.getShopAuthNeedUpdateStatus();
        list.forEach(item -> queryApplyStatusByApplymentId(item.getApplymentId(), item.getShopId()));
    }
    /**
     * 调用微信接口查询申请审核状态
     * @param applymentId
     */
    private void queryApplyStatusByApplymentId(String applymentId, Long shopId) {
        try {
            if (StringUtils.isNotBlank(applymentId)) {
                ApplymentsStatusResult result = wechatPayUtils.queryApplyStatusByApplymentId(applymentId);
                shopAuthenticationService.updateAuditStatusByApplymentId(applymentId, result);
                String applymentState = result.getApplymentState();
                if(WxApplyMentStateEnum.FINISH.getText().equals(applymentState)){
                    applySuccessUpdateShopStatus(shopId);
                }
            }
        } catch (WxPayException e) {
            e.printStackTrace();
        }
    }
    /**
     * 商户进件审核完成,更新商户状态
     * @param shopId
     */
    private void applySuccessUpdateShopStatus(Long shopId){
        // 更新商户状态为正常
        Shop shop = this.getById(shopId);
        Integer shopStatus = handelShopStatus(shop.getFrozenFlag(), shop.getCooperativeFlag(), 1);
        LambdaUpdateWrapper<Shop> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(Shop::getShopId, shopId)
                .set(Shop::getShopStatus, shopStatus)
                .set(Shop::getAuthFlag, 1);
        this.update(updateWrapper);
    }
}
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/shop/ShopAuthenticationService.java
@@ -1,7 +1,10 @@
package com.ruoyi.shop.service.shop;
import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsStatusResult;
import com.ruoyi.shop.domain.pojo.shop.ShopAuthentication;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
 * <p>
@@ -13,4 +16,23 @@
 */
public interface ShopAuthenticationService extends IService<ShopAuthentication> {
    /**
     * 获取需要更新状态的 微信二级商户认证审核
     * @return
     */
    List<ShopAuthentication> getShopAuthNeedUpdateStatus();
    /**
     * 修改微信审核状态
     * @param applymentId
     * @param result
     */
    void updateAuditStatusByApplymentId(String applymentId, ApplymentsStatusResult result);
    /**
     * 获取商户认证信息
     * @param shopId
     * @return
     */
    ShopAuthentication getByShopId(Long shopId);
}
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/shop/ShopProportionService.java
@@ -22,4 +22,11 @@
     * @return  void
     */
    void editMgtShopProportion(MgtShopProportionEditDto mgtShopProportionEditDto);
    /**
     * 获取商户分成比例
     * @param shopId
     * @return
     */
    ShopProportion getByShopId(Long shopId);
}
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/shop/ShopService.java
@@ -327,4 +327,9 @@
     * @return  void
     */
    void editShopCustomStatus(StaffShopCCEditDto staffShopCCEditDto);
    /**
     * 微信二级商户进件状态 定时任务检测
     */
    void queryEcommerceApplyMentsStatus();
}
ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/WechatPayUtils.java
@@ -1,8 +1,18 @@
package com.ruoyi.shop.util;
import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsRequest;
import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsResult;
import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsStatusResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.EcommerceService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.ruoyi.shop.domain.pojo.shop.ShopAuthentication;
import com.ruoyi.system.api.domain.poji.shop.Shop;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
 * 微信支付
@@ -11,12 +21,12 @@
@AllArgsConstructor
public class WechatPayUtils {
    //private final WxPayService wxService;
    private final WxPayService wxService;
    /**
     * 电商二级商户进件(提交申请单)
     */
    /*public void ecommerceApply(ShopAuthentication shopAuthentication, String applyNumber, Shop shop) throws WxPayException {
    public ApplymentsResult ecommerceApply(ShopAuthentication shopAuthentication, String applyNumber, Shop shop) throws WxPayException {
        EcommerceService ecommerceService = wxService.getEcommerceService();
        ApplymentsRequest request = new ApplymentsRequest();
        //生成提交类
@@ -96,18 +106,18 @@
        request.setBusinessAdditionPics(shopAuthentication.getBaPics());
        request.setBusinessAdditionDesc(shopAuthentication.getBaDesc());
        ApplymentsResult result = ecommerceService.createApply(request);
        return ecommerceService.createApply(request);
    }
    *//**
    /**
     * 通过查询申请状态API查询二级商户入驻申请结果
     * @param applyNumber 业务申请编号
     * @param applymentId 微信支付申请单号
     * @return 申请状态
     * @throws WxPayException
     *//*
    public ApplymentsStatusResult queryApplyStatusByOutRequestNo(String applyNumber) throws WxPayException {
        return wxService.getEcommerceService().queryApplyStatusByOutRequestNo(applyNumber);
    }*/
     */
    public ApplymentsStatusResult queryApplyStatusByApplymentId(String applymentId) throws WxPayException {
        return wxService.getEcommerceService().queryApplyStatusByApplymentId(applymentId);
    }
}