talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantWorkService.java
@@ -91,7 +91,7 @@
                   o.merchant_id, m.merchant_name, m.merchant_rights_config,
                   o.product_id, o.product_name_snapshot, p.rights_config,
                   o.order_type, o.order_amount, o.base_pay_amount, o.coupon_amount,
                   o.subsidy_amount, o.pay_amount, o.order_status, o.verify_status, o.withdrawal_status, o.created_at,
                   o.subsidy_amount, o.pay_amount, o.order_status, o.verify_status, o.created_at,
                   vr.verify_time, vr.status as verify_record_status
            from benefit_order o
            left join talent_user tu on tu.id = o.talent_id
@@ -251,8 +251,8 @@
            """, orderId, principal.merchantId(), principal.storeId());
      if (orders.isEmpty()) throw new BusinessException(ErrorCode.NOT_FOUND, "订单不存在");
      Map<String, Object> order = orders.get(0);
      // 撤销核销与核销、退款、提现锁定共用同一把订单行锁;锁内读到的核销记录才是稳定的。
      orderFundBoundary.lock(orderId).requireRevocable();
      // 撤销核销与核销、退款共用同一把订单行锁;锁内读到的核销记录才是稳定的。
      orderFundBoundary.lock(orderId);
      if (!"GROUP_BUY".equals(String.valueOf(order.get("orderType")))) {
         throw new BusinessException(ErrorCode.CONFLICT, "当前业务类型不支持撤销核销");
      }
@@ -283,8 +283,7 @@
      return result;
   }
   private String revokeReason(String orderType, boolean withdrawalLocked) {
      if (withdrawalLocked) return "订单已进入提现记录";
   private String revokeReason(String orderType) {
      return "GROUP_BUY".equals(orderType) ? "已过可撤销时间" : "当前业务类型不支持撤销核销";
   }
@@ -327,13 +326,10 @@
      result.put("couponAmount", couponAmount);
      // 免费入住没有 benefit_order 金额,补贴来自核销记录中的后台配置,不能按原价减实付覆盖为 0。
      result.put("subsidyAmount", "FREE_STAY".equals(orderType) ? configuredSubsidyAmount : totalDiscount);
      // 已进入提现记录的订单不能再撤销核销,商户端不值得展示一个必然失败的按钮。
      Long withdrawalStatus = number(order.get("withdrawalStatus"));
      boolean withdrawalLocked = withdrawalStatus != null && withdrawalStatus == 1;
      boolean canRevoke = "GROUP_BUY".equals(orderType) && verifyTime != null && Duration.between(verifyTime, LocalDateTime.now()).toHours() < REVOCATION_HOURS && verifyStatus != null && verifyStatus == 1 && !withdrawalLocked;
      boolean canRevoke = "GROUP_BUY".equals(orderType) && verifyTime != null && Duration.between(verifyTime, LocalDateTime.now()).toHours() < REVOCATION_HOURS && verifyStatus != null && verifyStatus == 1;
      result.put("canRevoke", canRevoke);
      result.put("revokeDeadline", verifyTime == null ? null : verifyTime.plusHours(REVOCATION_HOURS).toString());
      result.put("revokeReason", canRevoke ? "" : revokeReason(orderType, withdrawalLocked));
      result.put("revokeReason", canRevoke ? "" : revokeReason(orderType));
      return result;
   }