Merge #128 into master from cc_20250512_uploadRentContract
feat:租赁合同新增审批记录
* cc_20250512_uploadRentContract: (100 commits squashed)
- fix:计划闭店时间修改
- Merge branch 'cc_20250922_closeStore_w' into cc_20250514_common_bak
- feat:新签调整
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-common/src/main/java/com/cool/store/enums/UserRoleEnum.java
- fix:闭店信息新增初审、复审、终审时间字段;闭店管理列表新增返回字段
- Merge branch 'cc_20250922_closeStore_w' into cc_20250514_common_bak
- feat:招商
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-common/src/main/java/com/cool/store/enums/UserRoleEnum.java
- feat:招商
- feat:招商
- feat:招商
- fix:删除字段
- Merge branch 'cc_20250922_closeStore_w' into cc_20250514_common_bak
- feat:招商
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- Merge remote-tracking branch 'origin/cc_20250514_common_bak' into cc_20250514_common_bak
- feat:数据同步 名称新增MX 等前缀
- feat:上海魔盒未来食品有限公司
- fix:修改查询逻辑
- Merge branch 'cc_20260428_store_report' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-web/src/main/java/com/cool/store/job/XxlJobHandler.java
- feat:id
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- Merge remote-tracking branch 'origin/cc_20250514_common_bak' into cc_20250514_common_bak
- Merge branch 'cc_20260507_smz' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-service/src/main/java/com/cool/store/service/impl/SyncDataServiceImpl.java
- Merge remote-tracking branch 'origin/cc_20250514_common_bak' into cc_20250514_common_bak
- feat:翻新
- feat:用户列表为空
- Merge branch 'cc_20260427_rnewal' into cc_20250514_common_bak
- feat:用户列表为空
- Merge branch 'cc_20260427_rnewal' into cc_20250514_common_bak
- feat:RenewalRenovateApprovalVO
- Merge branch 'cc_20260427_rnewal' into cc_20250514_common_bak
- feat:招商副总裁
- Merge branch 'cc_20260427_rnewal' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-common/src/main/java/com/cool/store/enums/point/ShopSubStageStatusEnum.java
- feat:招商副总裁审核
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- feat:费用单调整
- feat:招商经理
- feat:招商经理
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- feat:费用调整
- Merge branch 'master' into cc_20260226_fix
- fix:bug修复
- fix:未开业门店试营业日期
- Merge branch 'cc_20260508_open_store_req' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-dao/src/main/java/com/cool/store/dao/StoreDao.java
#	coolstore-partner-dao/src/main/java/com/cool/store/mapper/StoreMapper.java
#	coolstore-partner-dao/src/main/resources/mapper/StoreMapper.xml
#	coolstore-partner-web/src/main/java/com/cool/store/job/XxlJobHandler.java
- feat:新增审批
- fix:开业日期报备不同步门店状态
- Merge branch 'cc_20260508_open_store_req' into cc_20250514_common_bak
- fix:字段名称修改
- Merge branch 'cc_20250922_closeStore_w' into cc_20250514_common_bak
- fix:闭店中止新增审批记录
- Merge branch 'cc_20250922_closeStore_w' into cc_20250514_common_bak
- feat:费用调整单
- feat:招商大区总审核 或者 分部内勤审核 其他状态不能审核
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- feat:调整单
- feat:SHOP_SUB_STAGE_STATUS_150_5
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- fix:试营业测试接口
- Merge remote-tracking branch 'origin/cc_20250514_common_bak' into cc_20250514_common_bak
- Merge branch 'master' into cc_20250514_common_bak
- feat:page
- feat:自动分账
- Merge branch 'master' into cc_20250514_common_bak
- fix:私域二维码门店绑定关系缓存改为7天
- Merge branch 'cc_20260226_fix' into cc_20250514_common_bak
- feat:getAuthRegionIdAndSubRegionIdExcludeStoreByUserId 优化开店管理查询
- Merge branch 'cc_20260509_fix' into cc_20250514_common_bak
- fix:修改门店开业日期判断条件修改
- Merge branch 'cc_20260508_open_store_req' into cc_20250514_common_bak
- feat:填写添加门店
- feat:建店代办处理
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- Merge branch 'cc_20260508_adjustment' into cc_20250514_common_bak
- feat:userAuthMappingService
- feat:addShopDecorationLog
- Merge branch 'cc_20260506_newsign' into cc_20250514_common_bak
- feat:待采购确认 审批流程
- feat:问题修复
- Merge branch 'cc_20260511_fix' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-dao/src/main/java/com/cool/store/dao/ShopStageInfoDAO.java
#	coolstore-partner-dao/src/main/java/com/cool/store/dao/StoreDao.java
#	coolstore-partner-dao/src/main/java/com/cool/store/mapper/ShopStageInfoMapper.java
#	coolstore-partner-dao/src/main/java/com/cool/store/mapper/StoreMapper.java
#	coolstore-partner-dao/src/main/resources/mapper/ShopStageInfoMapper.xml
#	coolstore-partner-dao/src/main/resources/mapper/StoreMapper.xml
#	coolstore-partner-service/src/main/java/com/cool/store/service/impl/PointServiceImpl.java
#	coolstore-partner-service/src/main/java/com/cool/store/service/impl/SignFranchiseServiceImpl.java
#	coolstore-partner-web/src/main/java/com/cool/store/job/XxlJobHandler.java
- feat:问题修复
- feat:问题修复
- feat:流水查询条件
- Merge branch 'master' into cc_20260508_adjustment
- feat:费用流水筛选条件
- fix:歇业管理逻辑修改
- Merge branch 'cc_20260508_adjustment' into cc_20250514_common_bak
- feat:getAdjustAmount
- Merge branch 'cc_20260511_close_up_modify' into cc_20260408_close_up
# Conflicts:
#	coolstore-partner-common/src/main/java/com/cool/store/enums/ErrorCodeEnum.java
#	coolstore-partner-common/src/main/java/com/cool/store/enums/RocketMqGroupEnum.java
#	coolstore-partner-common/src/main/java/com/cool/store/enums/RocketMqTagEnum.java
#	coolstore-partner-common/src/main/java/com/cool/store/enums/closeup/CloseUpPlatformEnum.java
#	coolstore-partner-dao/src/main/java/com/cool/store/dao/closeup/CloseUpPlatformDAO.java
#	coolstore-partner-dao/src/main/java/com/cool/store/mapper/StoreMapper.java
#	coolstore-partner-dao/src/main/java/com/cool/store/mapper/closeup/CloseUpPlatformMapper.java
#	coolstore-partner-dao/src/main/resources/mapper/StoreMapper.xml
#	coolstore-partner-dao/src/main/resources/mapper/closeup/CloseUpApplyFormMapper.xml
#	coolstore-partner-dao/src/main/resources/mapper/closeup/CloseUpPlatformMapper.xml
#	coolstore-partner-model/src/main/java/com/cool/store/entity/closeup/CloseUpApplyFormDO.java
#	coolstore-partner-model/src/main/java/com/cool/store/entity/closeup/CloseUpPlatformDO.java
#	coolstore-partner-service/src/main/java/com/cool/store/mq/consumer/ConsumerClient.java
#	coolstore-partner-service/src/main/java/com/cool/store/service/closeup/CloseUpService.java
#	coolstore-partner-service/src/main/java/com/cool/store/service/closeup/impl/CloseUpServiceImpl.java
#	coolstore-partner-web/src/main/java/com/cool/store/controller/webb/PCTestController.java
#	coolstore-partner-web/src/main/java/com/cool/store/job/XxlJobHandler.java
#	coolstore-partner-web/src/main/resources/application-ab.properties
#	coolstore-partner-web/src/main/resources/application-local.properties
#	coolstore-partner-web/src/main/resources/application-online.properties
#	coolstore-partner-web/src/main/resources/application-test.properties
- fix:合并冲突
- Merge branch 'cc_20260408_close_up' into cc_20250514_common_bak
# Conflicts:
#	coolstore-partner-common/src/main/java/com/cool/store/enums/ErrorCodeEnum.java
#	coolstore-partner-dao/src/main/java/com/cool/store/dao/StoreDao.java
#	coolstore-partner-service/src/main/java/com/cool/store/service/closeup/impl/CloseUpServiceImpl.java
#	coolstore-partner-web/src/main/java/com/cool/store/controller/webb/PCTestController.java
#	coolstore-partner-web/src/main/java/com/cool/store/job/XxlJobHandler.java
- fix:合并冲突
- Merge branch 'cc_20260508_adjustment' into cc_20250514_common_bak
- Merge branch 'master' into cc_20260408_close_up
- fix:火码歇业时机修改
- Merge branch 'cc_20260408_close_up' into cc_20250514_common_bak
- feat:租赁合同新增审批记录
- Merge branch 'master' into cc_20250512_uploadRentContract
# Conflicts:
#	coolstore-partner-service/src/main/java/com/cool/store/service/closeup/impl/CloseUpServiceImpl.java
#	coolstore-partner-service/src/main/java/com/cool/store/service/impl/PointServiceImpl.java
#	coolstore-partner-web/src/main/java/com/cool/store/controller/webb/PCTestController.java
- feat:merge冲突
- feat:merge冲突
Signed-off-by: 正新 <accounts_6964c7bcd2a2c377c5bbd01b@mail.teambition.com>
Merged-by: 正新 <accounts_6964c7bcd2a2c377c5bbd01b@mail.teambition.com>
CR-link: https://codeup.aliyun.com/692ea314dec569489f6f167c/hangzhou/java/custom_zxjp/change/128
This commit is contained in:
@@ -231,6 +231,11 @@ public class RedisConstant {
|
||||
|
||||
public static final String PHONE_NUMBER= "phone_number_";
|
||||
|
||||
public static final String ACCESS_TOKEN_CACHE_PREFIX = "liepin:access_token:{0}:{1}";
|
||||
|
||||
public static final String TOKEN_CACHE_PREFIX = "liepin:token:{0}:{1}";
|
||||
|
||||
public static final String LIE_PIN_EMP_PATH_PREFIX = "liepin:path:{0}:{1}";
|
||||
/**
|
||||
* MDM 省市区数据缓存
|
||||
*/
|
||||
@@ -352,6 +357,11 @@ public class RedisConstant {
|
||||
*/
|
||||
public static final String TP_PENALTY_APPLY_IMPORT_LOCK = "tp_penalty_apply_import_lock";
|
||||
|
||||
/**
|
||||
* 合同导入锁
|
||||
*/
|
||||
public static final String CONTRACT_IMPORT_LOCK = "contract_import_lock";
|
||||
|
||||
/**
|
||||
* 十二分审批按钮权限id
|
||||
*/
|
||||
@@ -360,6 +370,7 @@ public class RedisConstant {
|
||||
|
||||
public static final String STANDARD_STORE_PAY_LOCK_KEY = "standard_store_pay_lock_key:{0}";
|
||||
|
||||
|
||||
/**
|
||||
* 拜访记录导出锁
|
||||
*/
|
||||
|
||||
@@ -8,7 +8,8 @@ package com.cool.store.enums;
|
||||
*/
|
||||
public enum ClaimStatusEnum {
|
||||
TO_BE_CLAIMED(0,"待认领"),
|
||||
CLAIMED(1,"已认领");
|
||||
CLAIMED(1,"已认领"),
|
||||
CLAIMED_FAIL(2,"认领失败");
|
||||
private Integer code;
|
||||
private String message;
|
||||
ClaimStatusEnum(Integer code,String message){
|
||||
|
||||
@@ -224,6 +224,12 @@ public enum ErrorCodeEnum {
|
||||
|
||||
SYSTEM_NAME_NOT__SUPPORT(109018, "请不要使用系统默认店名!", null),
|
||||
|
||||
BANK_INFO_IS_EXIST(109017, "该区域已存在相同品牌,付款方式的银行信息!", null),
|
||||
SHOP_REGION_NOT_EXIST(109018, "门店未选择所属大区!", null),
|
||||
SHOP_FRANCHISE_BRAND_NOT_EXITS(109019, "门店未选择所属品牌!", null),
|
||||
PAY_TYPE_NOT_EXIST(109020, "付款方式异常!", null),
|
||||
RECEIVING_BANK_NOT_EXIST(109021, "未查询到该门店对应的收款银行信息", null),
|
||||
THERE_ARE_SEVERAL_RECEIVING_BANK(109022, "该门店已存在多个收款银行信息!", null),
|
||||
|
||||
INSERT_OPENING_OPERATION_PLAN_AUDIT_FALSE(103001,"插入运营方案审核信息失败",null),
|
||||
INSERT_OPENING_OPERATION_PLAN_FALSE(103002,"插入运营方案失败",null),
|
||||
@@ -320,9 +326,13 @@ public enum ErrorCodeEnum {
|
||||
STORE_MESSAGE_REVOKE(1610003,"当前门店消息已撤销,请务重复操作",null),
|
||||
STORE_MESSAGE_HANDLED(1610004,"当前门店消息已处理,无法撤销!",null),
|
||||
MATTER_STORE_OR_USER_IS_NULL(1610005,"当前事项门店或者人员为空,发布失败,请确认!",null),
|
||||
CONFIG_NOT_EXIST(1610006,"配置不存在或被禁用,请确认!",null),
|
||||
CONFIG_NOT_EXIST(1016006,"配置不存在或被禁用,请确认!",null),
|
||||
MESSAGE_NOT_EXIST(1610007,"消息模板不存在或已被删除",null),
|
||||
MESSAGE_NOT_HANDLED(1610008,"当前消息无需处理,请确认消息处理类型!",null),
|
||||
|
||||
FILE_ERROR(1610001,"文件解析失败",null),
|
||||
|
||||
|
||||
MESSAGE_PUBLISH(1610009,"您选择通知任务正在发布中,请稍后重试!",null),
|
||||
|
||||
NOT_FLAGSHIP_STORE(16100005,"非直营店,无法跳过缴费阶段!",null),
|
||||
@@ -333,7 +343,6 @@ public enum ErrorCodeEnum {
|
||||
JOIN_MODE_NOT_ALLOW_OPERATE(1610012,"加盟部人员只能新建加盟店或联营店,请确认!",null),
|
||||
STORE_NOT_FIND(1610013,"门店不存在",null),
|
||||
SHOP_NAME_INVALID(1610014, "门店名称包含禁止关键词",null),
|
||||
CONTRACT_STAGE_NO_COMPLETE(1610015, "当前阶段无法分配运营顾问!",null),
|
||||
|
||||
CONFIG_OPTION_USED(1610015, "配置选项已被店型使用,无法删除", null),
|
||||
STORE_TYPE_OPTION_DEFAULT_DUPLICATE(1610016, "同一配置项下只能设置一个默认选项", null),
|
||||
@@ -371,6 +380,8 @@ public enum ErrorCodeEnum {
|
||||
|
||||
|
||||
|
||||
CONTRACT_STAGE_NO_COMPLETE(1610015, "当前阶段无法分配运营顾问!",null),
|
||||
|
||||
//装修
|
||||
TEAM_USED(1612001,"该装修团队有门店使用,无法删除,请确认!",null),
|
||||
CURRENT_BRAND_SORT_NUMBER_EXIST(1612002,"已存在该排序数字!",null),
|
||||
@@ -399,6 +410,7 @@ public enum ErrorCodeEnum {
|
||||
WITHDRAW_APPLY_NOT_EXIST(1621011, "提现申请单不存在!", null),
|
||||
WITHDRAW_ING(1621012, "提现中,请勿重复分账!", null),
|
||||
WALLET_BALANCE_INSUFFICIENT(1621013, "钱包余额不足!", null),
|
||||
WALLET_OPEN_ACCOUNT_NO_BALANCE(1621014,"认款失败,该门店钱包余额不足!",null),
|
||||
|
||||
|
||||
|
||||
@@ -478,10 +490,7 @@ public enum ErrorCodeEnum {
|
||||
WALLET_PAY_CANNOT_CANCEL(1830020, "该交易无法取消", null),
|
||||
TOTAL_FEES_NEED_EQUAL(1830021, "分账总金额需与合计缴费金额一致", null),
|
||||
NOT_EXIST_WANG_SHANG_ACCOUNT(1830022, "当前门店未开通网商钱包账户,请先开通!", null),
|
||||
SIGNER_NOT_EQUAL_LEGAL_PERSON(1840022, "法人与签约人不一致", null),
|
||||
|
||||
IP_LIMIT(1840000, "IP访问次数超限", null),
|
||||
|
||||
SIGNER_NOT_EQUAL_LEGAL_PERSON(1840023, "法人与签约人不一致", null),
|
||||
|
||||
CLOSE_UP_CLOSED_DOWN(1840000, "门店已歇业", null),
|
||||
CLOSE_UP_ONLY_SUPPORT_OPEN(1840001, "仅支持在营门店发起歇业申请", null),
|
||||
@@ -495,12 +504,40 @@ public enum ErrorCodeEnum {
|
||||
CLOSE_UP_EXIST_OPEN_APPLY(1840009, "该歇业申请单已存在开业申请", null),
|
||||
CLOSE_UP_APPROVED(1840010, "该申请单已审批", null),
|
||||
|
||||
IP_LIMIT(1840000, "IP访问次数超限", null),
|
||||
|
||||
// 考试模块 190xxx
|
||||
EXAM_QUESTION_NOT_EXIST(190001, "题目不存在", null),
|
||||
EXAM_PAPER_NOT_EXIST(190002, "试卷不存在", null),
|
||||
EXAM_INFO_NOT_EXIST(190003, "考试不存在", null),
|
||||
EXAM_PAPER_STARTED_CANNOT_EDIT(190004, "试卷已开始考试,不可修改", null),
|
||||
EXAM_NOT_PUBLISHED(190005, "考试未发布", null),
|
||||
EXAM_ALREADY_ENDED(190006, "考试已结束", null),
|
||||
EXAM_ATTEMPT_NOT_EXIST(190007, "答卷不存在", null),
|
||||
EXAM_ATTEMPT_ALREADY_SUBMITTED(190008, "试卷已提交,请勿重复提交", null),
|
||||
EXAM_ATTEMPT_EXPIRED(190009, "考试时间已到,已自动提交", null),
|
||||
EXAM_TOKEN_INVALID(190010, "考试链接无效", null),
|
||||
EXAM_ATTEMPT_IN_PROGRESS(190011, "您有正在进行的考试,请先完成", null),
|
||||
EXAM_ALREADY_PUBLISHED(190012, "考试已发布,无法重复发布", null),
|
||||
EXAM_NOT_STARTED(190013, "考试未开始", null),
|
||||
EXAM_TIME_ENDED(190014, "考试时间已结束", null),
|
||||
EXAM_IN_PROGRESS_CANNOT_DELETE(190015, "当前考试进行中,请先结束考试", null),
|
||||
EXAM_COMPLETED(190016, "已完成该考试", null),
|
||||
|
||||
BONUS_EXIST_OVERLAP_RULE(1850000, "门店该有效期范围内存在相同类型的启用规则", null),
|
||||
BONUS_RULE_NOT_EXIST(1850001, "不存在该奖金发放规则", null),
|
||||
BONUS_RULE_NOT_CONFIG(1850002, "奖金规则或分配规则未配置", null),
|
||||
BONUS_DISTRIBUTE_RATIO_OVER_100(1850003, "分配规则员工比例之和大于100", null),
|
||||
BONUS_PRODUCT_CONFIG_DUPLICATE(1850004, "奖金规则配置存在重复菜品", null),
|
||||
BONUS_RULE_CONFIG_ERROR(1850005, "规则配置异常", null),
|
||||
|
||||
|
||||
//续签
|
||||
RENEWAL_CONTRACT_NOT_EXIST(1850000,"当前门店没有合同信息",null),
|
||||
CURRENT_SHOP_EXIST_APPLY(1850002,"当前门店有正在续签的申请",null),
|
||||
RENEWAL_APPLY_NOT_EXIST(1850003,"续签申请不存在",null),
|
||||
|
||||
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.cool.store.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 答卷状态枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ExamAttemptStatusEnum {
|
||||
|
||||
IN_PROGRESS(0, "进行中"),
|
||||
COMPLETED(1, "已完成");
|
||||
|
||||
private final Integer code;
|
||||
private final String desc;
|
||||
|
||||
/**
|
||||
* 是否为进行中状态
|
||||
*/
|
||||
public static boolean isInProgress(Integer code) {
|
||||
return IN_PROGRESS.getCode().equals(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为已完成状态
|
||||
*/
|
||||
public static boolean isCompleted(Integer code) {
|
||||
return COMPLETED.getCode().equals(code);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.cool.store.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 考试信息状态枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ExamInfoStatusEnum {
|
||||
|
||||
UN_PUBLISHED(0, "未发布"),
|
||||
PUBLISHED(1, "已发布"),
|
||||
ENDED(2, "已结束");
|
||||
|
||||
private final Integer code;
|
||||
private final String desc;
|
||||
|
||||
/**
|
||||
* 根据code获取枚举
|
||||
*/
|
||||
public static ExamInfoStatusEnum getByCode(Integer code) {
|
||||
if (code == null) {
|
||||
return null;
|
||||
}
|
||||
for (ExamInfoStatusEnum statusEnum : values()) {
|
||||
if (statusEnum.getCode().equals(code)) {
|
||||
return statusEnum;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为未发布状态
|
||||
*/
|
||||
public static boolean isUnPublished(Integer code) {
|
||||
return UN_PUBLISHED.getCode().equals(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为已发布状态
|
||||
*/
|
||||
public static boolean isPublished(Integer code) {
|
||||
return PUBLISHED.getCode().equals(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为已结束状态
|
||||
*/
|
||||
public static boolean isEnded(Integer code) {
|
||||
return ENDED.getCode().equals(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可以发布(只有未发布状态可以发布)
|
||||
*/
|
||||
public static boolean canPublish(Integer code) {
|
||||
return isUnPublished(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可以结束(只有已发布状态可以结束)
|
||||
*/
|
||||
public static boolean canEnd(Integer code) {
|
||||
return isPublished(code);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ public enum FileTypeEnum {
|
||||
IMPORT_FITMENT_SHOP_STAGE_DATA_ERROR_LIST("OaOldShopStageDataErrorList", "导入装修阶段完成数据错误列表 "),
|
||||
SELLING_DETAILS_REPORT("sellingDetailsReport", "开店明细报表"),
|
||||
PRE_FRY_QUALIFICATION_APPLY_EXPORT("preFryQualificationApplyExport", "预炸品资质申请导出"),
|
||||
RECEIVING_BANK_IMPORT("Receiving_Bank_Import", "收款银行配置导入"),
|
||||
TP_PENALTY_IMPORT("tpPenaltyImport", "十二分惩处申请单导入"),
|
||||
TP_PENALTY_ERROR_EXPORT("tpPenaltyErrorExport", "十二分惩处申请单导入错误列表"),
|
||||
VISIT_RECORD_EXPORT("visitRecordExport", "拜访记录列表"),
|
||||
@@ -38,6 +39,8 @@ public enum FileTypeEnum {
|
||||
ADJUSTMENT_ORDER_EXPORT("adjustmentOrderExport", "费用调整单导出"),
|
||||
EXPENSE_ORDER_EXPORT("expenseOrderExport", "费用单导出"),
|
||||
SPLIT_ORDER_EXPORT("splitOrderExport", "分账单导出"),
|
||||
CONTRACT_IMPORT("contractImport", "合同导入"),
|
||||
CONTRACT_ERROR_EXPORT("contractErrorExport", "合同导入错误列表"),
|
||||
;
|
||||
private String fileType;
|
||||
private String desc;
|
||||
|
||||
@@ -104,4 +104,16 @@ public enum FranchiseBrandEnum {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Integer getCodeByDesc(String desc) {
|
||||
if (StringUtils.isBlank(desc)){
|
||||
return null;
|
||||
}
|
||||
for (FranchiseBrandEnum e : FranchiseBrandEnum.values()) {
|
||||
if (desc.equals(e.getDesc())) {
|
||||
return e.getCode();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.cool.store.enums;
|
||||
|
||||
/**
|
||||
* @Author: WangShuo
|
||||
* @Date: 2025/06/13/15:08
|
||||
* @Version 1.0
|
||||
* @注释:
|
||||
*/
|
||||
public enum IsRefundEnum {
|
||||
|
||||
NOT_REFUND(0, "未退款"),
|
||||
REFUND(1, "已退款");
|
||||
private Integer code;
|
||||
private String message;
|
||||
IsRefundEnum(Integer code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.cool.store.enums;
|
||||
|
||||
/**
|
||||
* @Author: WangShuo
|
||||
* @Date: 2025/06/16/14:08
|
||||
* @Version 1.0
|
||||
* @注释:
|
||||
*/
|
||||
public enum PayStatusEnum {
|
||||
|
||||
WAIT_PAY_45(45,"待支付"),
|
||||
FEES_HAVE_BEEN_PAID_50(50,"已缴费"),
|
||||
PAY_FAIL_55(55,"缴费失败"),
|
||||
CANCELED(60,"已取消");
|
||||
private Integer code;
|
||||
private String message;
|
||||
|
||||
PayStatusEnum(Integer code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,6 +39,8 @@ public enum RocketMqGroupEnum {
|
||||
STORE_MASTER_ISSUE("store_master_issue", new ArrayList<>(Arrays.asList(RocketMqTagEnum.STORE_MASTER_ISSUE))),
|
||||
VISIT_RECORD_INVALID("visit_record_invalid", new ArrayList<>(Arrays.asList(RocketMqTagEnum.VISIT_RECORD_INVALID))),
|
||||
TP_PENALTY_APPEAL_OVERDUE("tp_penalty_appeal_overdue", new ArrayList<>(Arrays.asList(RocketMqTagEnum.TP_PENALTY_APPEAL_OVERDUE))),
|
||||
EXAM_AUTO_SUBMIT("exam_auto_submit", new ArrayList<>(Arrays.asList(RocketMqTagEnum.EXAM_AUTO_SUBMIT))),
|
||||
EXAM_AUTO_END("exam_auto_end", new ArrayList<>(Arrays.asList(RocketMqTagEnum.EXAM_AUTO_END))),
|
||||
CLOSE_UP_APPLY_STORE_UPDATE("close_up_apply_store_update", new ArrayList<>(Arrays.asList(RocketMqTagEnum.CLOSE_UP_APPLY_STORE_UPDATE))),
|
||||
CLOSE_UP_PLAN_OPEN_STORE("close_up_plan_open_store", new ArrayList<>(Arrays.asList(RocketMqTagEnum.CLOSE_UP_PLAN_OPEN_STORE))),
|
||||
;
|
||||
|
||||
@@ -23,6 +23,8 @@ public enum RocketMqTagEnum {
|
||||
STORE_MASTER_ISSUE("store_master_issue","门店主数据下发"),
|
||||
VISIT_RECORD_INVALID("visit_record_invalid", "拜访记录失效"),
|
||||
TP_PENALTY_APPEAL_OVERDUE("tp_penalty_appeal_overdue", "十二分惩处单复议逾期"),
|
||||
EXAM_AUTO_SUBMIT("exam_auto_submit", "考试自动提交"),
|
||||
EXAM_AUTO_END("exam_auto_end", "考试自动结束"),
|
||||
CLOSE_UP_APPLY_STORE_UPDATE("close_up_apply_store_update", "歇业申请修改门店状态"),
|
||||
CLOSE_UP_PLAN_OPEN_STORE("close_up_plan_open_store", "歇业申请计划开店"),
|
||||
;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.cool.store.enums.approval;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 审批结果枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ApprovalResultEnum {
|
||||
|
||||
PASS("pass", "通过"),
|
||||
REJECT("reject", "拒绝"),
|
||||
;
|
||||
|
||||
private final String result;
|
||||
private final String name;
|
||||
|
||||
public static ApprovalResultEnum getByResult(String result) {
|
||||
for (ApprovalResultEnum value : values()) {
|
||||
if (value.getResult().equals(result)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.cool.store.enums.point;
|
||||
|
||||
import com.cool.store.utils.StringUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* @Auther: WangShuo
|
||||
* @Date: 2024/04/29/上午9:45
|
||||
@@ -9,7 +12,7 @@ package com.cool.store.enums.point;
|
||||
public enum PayTypeEnum {
|
||||
WX_PAY(1,"微信支付"),
|
||||
BANK_PAY(2,"银行转账"),
|
||||
ONLINE_PAY(3,"线上支付"),
|
||||
ONLINE_PAY(3,"加盟付"),
|
||||
OFFLINE_PAY(4,"线下支付");
|
||||
private Integer code;
|
||||
|
||||
@@ -27,4 +30,16 @@ public enum PayTypeEnum {
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public static Integer getCodeByDesc(String desc){
|
||||
if (StringUtils.isBlank(desc)){
|
||||
return null ;
|
||||
}
|
||||
for (PayTypeEnum value : PayTypeEnum.values()) {
|
||||
if(value.getDesc().equals(desc)){
|
||||
return value.getCode();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ public enum ShopStageEnum {
|
||||
SHOP_STAGE_1(1, "选址"),
|
||||
SHOP_STAGE_2(2, "筹建"),
|
||||
SHOP_STAGE_3(3, "平台建店"),
|
||||
SHOP_STAGE_4(4, "开业筹备"),
|
||||
;
|
||||
|
||||
//店铺阶段
|
||||
|
||||
@@ -25,7 +25,7 @@ public enum ShopSubStageEnum {
|
||||
SHOP_STAGE_9(ShopStageEnum.SHOP_STAGE_2, 90, "设计阶段", 14),
|
||||
SHOP_STAGE_11(ShopStageEnum.SHOP_STAGE_2, 110, "施工阶段", 25),
|
||||
SHOP_STAGE_12(ShopStageEnum.SHOP_STAGE_2, 120, "装修验收", 27),
|
||||
SHOP_STAGE_14(ShopStageEnum.SHOP_STAGE_2, 140, "开业运营方案", 28),
|
||||
SHOP_STAGE_14(ShopStageEnum.SHOP_STAGE_4, 140, "开业运营方案", 28),
|
||||
|
||||
SHOP_STAGE_15(ShopStageEnum.SHOP_STAGE_2, 150, "建店资料收集", 9),
|
||||
SHOP_STAGE_16(ShopStageEnum.SHOP_STAGE_2, 160, "POS开通", 10),
|
||||
|
||||
@@ -84,9 +84,7 @@ public enum ShopSubStageStatusEnum {
|
||||
SHOP_SUB_STAGE_STATUS_123(ShopSubStageEnum.SHOP_STAGE_12, 1230, "已验收", Boolean.TRUE),
|
||||
|
||||
//开业运营方案
|
||||
SHOP_SUB_STAGE_STATUS_140(ShopSubStageEnum.SHOP_STAGE_14, 1400, "待上传", Boolean.FALSE),
|
||||
SHOP_SUB_STAGE_STATUS_141(ShopSubStageEnum.SHOP_STAGE_14, 1420, "待审核", Boolean.FALSE),
|
||||
SHOP_SUB_STAGE_STATUS_142(ShopSubStageEnum.SHOP_STAGE_14, 1430,"审核不通过", Boolean.FALSE),
|
||||
SHOP_SUB_STAGE_STATUS_140(ShopSubStageEnum.SHOP_STAGE_14, 1400, "待督导提交", Boolean.FALSE),
|
||||
SHOP_SUB_STAGE_STATUS_143(ShopSubStageEnum.SHOP_STAGE_14, 1440, "已完成", Boolean.TRUE),
|
||||
|
||||
//平台资料提交
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.cool.store.enums.renewal;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 续签审批节点枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum RenewalNodeEnum {
|
||||
|
||||
FRANCHISEE_CONFIRM("10", "加盟商确认"),
|
||||
OPS_CONSULTANT("20", "运营顾问审核"),
|
||||
REGION_CONSULTANT("25", "片区顾问审核"),
|
||||
GROUP_ENGINEERING("30", "集团工程部审核"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
|
||||
public static RenewalNodeEnum getByCode(String code) {
|
||||
for (RenewalNodeEnum value : values()) {
|
||||
if (value.getCode().equals(code)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个审批节点code
|
||||
*/
|
||||
public static String getNextNode(String currentCode) {
|
||||
RenewalNodeEnum current = getByCode(currentCode);
|
||||
if (current == null) {
|
||||
return null;
|
||||
}
|
||||
switch (current) {
|
||||
case FRANCHISEE_CONFIRM:
|
||||
return OPS_CONSULTANT.getCode();
|
||||
case OPS_CONSULTANT:
|
||||
return REGION_CONSULTANT.getCode();
|
||||
case REGION_CONSULTANT:
|
||||
return GROUP_ENGINEERING.getCode();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getNameByCode(String code) {
|
||||
RenewalNodeEnum e = getByCode(code);
|
||||
return e != null ? e.getName() : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.cool.store.enums.renewal;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 续签申请状态枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum RenewalStatusEnum {
|
||||
|
||||
PENDING_FRANCHISEE(10, "待加盟商确认"),
|
||||
PENDING_OPS(20, "待运营顾问审核"),
|
||||
PENDING_REGION(25, "待片区顾问审核"),
|
||||
PENDING_GROUP(30, "待集团工程部审核"),
|
||||
REJECTED(40, "审批拒绝"),
|
||||
RENEWAL_ING(50, "续签中"),
|
||||
COMPLETED(60, "已完成"),
|
||||
NOT_RENEWED(70, "不续签"),
|
||||
;
|
||||
|
||||
private final Integer status;
|
||||
private final String name;
|
||||
|
||||
public static RenewalStatusEnum getByStatus(Integer status) {
|
||||
for (RenewalStatusEnum value : values()) {
|
||||
if (value.getStatus().equals(status)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getNameByStatus(Integer status) {
|
||||
RenewalStatusEnum e = getByStatus(status);
|
||||
return e != null ? e.getName() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个审批通过状态
|
||||
*/
|
||||
public static Integer getNextPassStatus(Integer status) {
|
||||
RenewalStatusEnum current = getByStatus(status);
|
||||
if (current == null) {
|
||||
throw new IllegalArgumentException("续签申请状态为空");
|
||||
}
|
||||
switch (current) {
|
||||
case PENDING_FRANCHISEE:
|
||||
return PENDING_OPS.getStatus();
|
||||
case PENDING_OPS:
|
||||
return PENDING_REGION.getStatus();
|
||||
case PENDING_REGION:
|
||||
return PENDING_GROUP.getStatus();
|
||||
case PENDING_GROUP:
|
||||
return COMPLETED.getStatus();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isApprove(Integer status) {
|
||||
return PENDING_FRANCHISEE.getStatus().equals(status)
|
||||
|| PENDING_OPS.getStatus().equals(status)
|
||||
|| PENDING_REGION.getStatus().equals(status)
|
||||
|| PENDING_GROUP.getStatus().equals(status);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.cool.store.enums.wallet;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Auther zx_szh
|
||||
* @Date 2026/4/9 09:35
|
||||
@@ -8,7 +11,9 @@ package com.cool.store.enums.wallet;
|
||||
public enum DocStatusEnum {
|
||||
|
||||
//10-待充值/20-已充值待认款/30-认款完成/40-分部分账/50-分账完成
|
||||
DOC_STATUS_05(5,"待审批"),
|
||||
DOC_STATUS_1(10,"待充值"),
|
||||
DOC_STATUS_15(15,"审批未通过"),
|
||||
DOC_STATUS_2(20,"已充值待认款"),
|
||||
DOC_STATUS_3(30,"认款完成"),
|
||||
DOC_STATUS_4(40,"部分分账"),
|
||||
@@ -32,6 +37,9 @@ public enum DocStatusEnum {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public static List<Integer> getCanDeleteStatus(){
|
||||
return Arrays.asList(DOC_STATUS_05.getStatus(),DOC_STATUS_1.getStatus(),DOC_STATUS_2.getStatus());
|
||||
}
|
||||
|
||||
public static DocStatusEnum fromStatus(Integer status) {
|
||||
for (DocStatusEnum item : values()) {
|
||||
|
||||
@@ -50,4 +50,9 @@ public class GenerateNoUtil {
|
||||
return SPLIT_ORDER_PREFIX + GenerateNoUtil.generateMillsNoWithRandom();
|
||||
}
|
||||
|
||||
|
||||
public static Long generateVersion() {
|
||||
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DATE_FORMAT_SEC_9);
|
||||
return Long.valueOf(LocalDateTime.now().format(dateFormatter));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.cool.store.utils;
|
||||
|
||||
import org.apache.tika.io.IOUtils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* @Author suzhuhong
|
||||
* @Date 2025/5/23 17:30
|
||||
* @Version 1.0
|
||||
*/
|
||||
public class OssUtil {
|
||||
|
||||
/**
|
||||
* 公用oss链接转为base64
|
||||
* @param ossUrl
|
||||
* @return
|
||||
*/
|
||||
public static String convertPublicOssUrlToBase64(String ossUrl) {
|
||||
try (InputStream in = new URL(ossUrl).openStream()) {
|
||||
byte[] fileBytes = IOUtils.toByteArray(in);
|
||||
return Base64.getEncoder().encodeToString(fileBytes);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to convert OSS URL to Base64", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取oss链接文件名
|
||||
* @param ossUrl
|
||||
* @return
|
||||
*/
|
||||
public static String getUrlName(String ossUrl){
|
||||
if (StringUtil.isEmpty(ossUrl)){
|
||||
return "";
|
||||
}
|
||||
return ossUrl.substring(ossUrl.lastIndexOf("/") + 1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.cool.store.utils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author suzhuhong
|
||||
* @Date 2025/6/11 13:59
|
||||
* @Version 1.0
|
||||
*/
|
||||
public class RealIpUtils {
|
||||
|
||||
// 常见代理服务器IP头(按优先级排序)
|
||||
private static final List<String> IP_HEADERS = Arrays.asList(
|
||||
"X-Real-IP",
|
||||
"X-Forwarded-For",
|
||||
"Proxy-Client-IP",
|
||||
"WL-Proxy-Client-IP",
|
||||
"HTTP_CLIENT_IP",
|
||||
"HTTP_X_FORWARDED_FOR"
|
||||
);
|
||||
|
||||
/**
|
||||
* 获取客户端真实IP地址
|
||||
* @param request HttpServletRequest对象
|
||||
* @return 可能的最接近客户端的IP地址
|
||||
*/
|
||||
public static String getRealClientIp(HttpServletRequest request) {
|
||||
// 1. 检查所有可能的代理头
|
||||
for (String header : IP_HEADERS) {
|
||||
String ip = request.getHeader(header);
|
||||
if (isValidIp(ip)) {
|
||||
return getFirstValidIp(ip);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 没有代理头时使用remoteAddr
|
||||
String remoteAddr = request.getRemoteAddr();
|
||||
|
||||
// 3. 处理IPv6本地地址
|
||||
if ("0:0:0:0:0:0:0:1".equals(remoteAddr) || "::1".equals(remoteAddr)) {
|
||||
return "127.0.0.1";
|
||||
}
|
||||
|
||||
return remoteAddr;
|
||||
}
|
||||
|
||||
private static boolean isValidIp(String ip) {
|
||||
return ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip);
|
||||
}
|
||||
|
||||
private static String getFirstValidIp(String ipChain) {
|
||||
if (ipChain.contains(",")) {
|
||||
// 可能有多个IP(X-Forwarded-For: client,proxy1,proxy2)
|
||||
String[] ips = ipChain.split(",");
|
||||
for (String ip : ips) {
|
||||
String trimmedIp = ip.trim();
|
||||
if (isValidIp(trimmedIp)) {
|
||||
return trimmedIp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ipChain.trim();
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import java.text.MessageFormat;
|
||||
public class RedisConstantUtil {
|
||||
|
||||
@Value("${spring.profiles.active}")
|
||||
private String active;
|
||||
private String active;
|
||||
|
||||
@Value("${mybatis.configuration.variables.enterpriseId}")
|
||||
private String eid;
|
||||
@@ -115,6 +115,17 @@ public class RedisConstantUtil {
|
||||
return active + "_" + RedisConstant.GET_AI_MODULE + eid;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取key的通用方法
|
||||
* @param prefix
|
||||
* @param args
|
||||
* @return
|
||||
*/
|
||||
public String getKeyCommonMethod(String prefix,String... args){
|
||||
return active + "_" + MessageFormat.format(prefix,args) ;
|
||||
}
|
||||
|
||||
|
||||
public String getPaymentReceiptCode(String today){
|
||||
return active + "_" + MessageFormat.format(RedisConstant.REDIS_KEY_PREFIX, today);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.cool.store.utils;
|
||||
|
||||
import cn.hutool.core.net.URLEncodeUtil;
|
||||
import cn.hutool.core.net.url.UrlQuery;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.digest.DigestAlgorithm;
|
||||
import cn.hutool.crypto.digest.Digester;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.TreeMap;
|
||||
/**
|
||||
* 猎聘薪超人 签名工具类
|
||||
* @Author suzhuhong
|
||||
* @Date 2025/5/20 15:53
|
||||
* @Version 1.0
|
||||
*/
|
||||
public class SuperPaySignature {
|
||||
private static final Digester SHA256 = new Digester(DigestAlgorithm.SHA256);
|
||||
|
||||
/**
|
||||
* 生成请求签名
|
||||
* @param httpMethod 请求方法(大写)如:POST
|
||||
* @param uri 接口路径 如:/api/v1/order
|
||||
* @param queryString 原始查询字符串 如:name=张三&age=30
|
||||
* @param appId 应用ID 如:1724436445613182976
|
||||
* @param requestBody 请求体内容
|
||||
* @param nonce 随机数 如UUID
|
||||
* @param timestamp 时间戳(毫秒)
|
||||
* @param secretKey 密钥
|
||||
* @return 签名值
|
||||
*/
|
||||
public static String generateSignature(String httpMethod,
|
||||
String uri,
|
||||
String queryString,
|
||||
String appId,
|
||||
byte[] requestBody,
|
||||
String nonce,
|
||||
long timestamp,
|
||||
String secretKey) {
|
||||
// 1. 规范化QueryString
|
||||
String canonicalizedQuery = canonicalizeQueryString(queryString);
|
||||
|
||||
// 2. 计算请求体哈希
|
||||
String payloadHash = calculatePayloadHash(requestBody);
|
||||
|
||||
// 3. 构建签名字符串
|
||||
String signatureString = buildSignatureString(
|
||||
httpMethod,
|
||||
uri,
|
||||
canonicalizedQuery,
|
||||
appId,
|
||||
payloadHash,
|
||||
nonce,
|
||||
timestamp,
|
||||
secretKey);
|
||||
|
||||
// 4. 计算SHA256签名
|
||||
return SHA256.digestHex(signatureString);
|
||||
}
|
||||
|
||||
private static String canonicalizeQueryString(String queryString) {
|
||||
if (StrUtil.isBlank(queryString)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
UrlQuery urlQuery = UrlQuery.of(queryString, StandardCharsets.UTF_8);
|
||||
TreeMap<String, String> sortedParams = new TreeMap<>();
|
||||
|
||||
urlQuery.getQueryMap().forEach((k, v) -> {
|
||||
String encodedKey = URLEncodeUtil.encode(k.toString(), StandardCharsets.UTF_8);
|
||||
String encodedValue = URLEncodeUtil.encode(v.toString(), StandardCharsets.UTF_8);
|
||||
sortedParams.put(encodedKey, encodedValue);
|
||||
});
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sortedParams.forEach((k, v) -> {
|
||||
if (sb.length() > 0) {
|
||||
sb.append("&");
|
||||
}
|
||||
sb.append(k).append("=").append(v);
|
||||
});
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String calculatePayloadHash(byte[] requestBody) {
|
||||
if (ArrayUtil.isEmpty(requestBody)) {
|
||||
return "";
|
||||
}
|
||||
return SHA256.digestHex(requestBody);
|
||||
}
|
||||
|
||||
private static String buildSignatureString(String httpMethod,
|
||||
String uri,
|
||||
String canonicalizedQuery,
|
||||
String appId,
|
||||
String payloadHash,
|
||||
String nonce,
|
||||
long timestamp,
|
||||
String secretKey) {
|
||||
return String.join("\n",
|
||||
httpMethod.toUpperCase(),
|
||||
uri,
|
||||
canonicalizedQuery,
|
||||
appId,
|
||||
payloadHash,
|
||||
nonce,
|
||||
String.valueOf(timestamp),
|
||||
secretKey
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.cool.store.utils.hire;
|
||||
|
||||
import cn.hutool.core.codec.Base64Decoder;
|
||||
import cn.hutool.core.codec.Base64Encoder;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.cool.store.exception.ServiceException;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class XbbAesUtil {
|
||||
|
||||
/**
|
||||
* 算法/加密模式/填充方式
|
||||
*/
|
||||
private static final String AES_PKCS5P = "AES/ECB/PKCS5Padding";
|
||||
|
||||
/**
|
||||
* 加密
|
||||
*
|
||||
* @param str 需要加密的字符串
|
||||
* @param key 密钥
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String encrypt(String str, String key) {
|
||||
if (StrUtil.isEmpty(key)) {
|
||||
throw new ServiceException("key不能为空");
|
||||
}
|
||||
try {
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
// 判断Key是否为16位
|
||||
if (key.length() != 16) {
|
||||
return null;
|
||||
}
|
||||
byte[] raw = key.getBytes(StandardCharsets.UTF_8);
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
|
||||
// "算法/模式/补码方式"
|
||||
Cipher cipher = Cipher.getInstance(AES_PKCS5P);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
|
||||
byte[] encrypted = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8));
|
||||
// 此处使用BASE64做转码功能,同时能起到2次加密的作用。
|
||||
return Base64Encoder.encode(encrypted);
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密
|
||||
*
|
||||
* @param str 需要解密的字符串
|
||||
* @param key 密钥
|
||||
* @return
|
||||
*/
|
||||
public static String decrypt(String str, String key) {
|
||||
if (StrUtil.isEmpty(key)) {
|
||||
throw new ServiceException("key不能为空");
|
||||
}
|
||||
try {
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
// 判断Key是否为16位
|
||||
if (key.length() != 16) {
|
||||
return null;
|
||||
}
|
||||
byte[] raw = key.getBytes(StandardCharsets.UTF_8);
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
|
||||
Cipher cipher = Cipher.getInstance(AES_PKCS5P);
|
||||
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
|
||||
// 先用base64解密
|
||||
byte[] encrypted = Base64Decoder.decode(str);
|
||||
try {
|
||||
byte[] original = cipher.doFinal(encrypted);
|
||||
return new String(original, StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package com.cool.store.utils.hire;
|
||||
|
||||
import cn.hutool.core.net.url.UrlQuery;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.digest.DigestAlgorithm;
|
||||
import cn.hutool.crypto.digest.Digester;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* 签名信息
|
||||
*
|
||||
* @author XBB-OpenAPI
|
||||
* @since 2025-03-27
|
||||
*/
|
||||
public class XbbSignatureInfo {
|
||||
private String httpMethod;
|
||||
private String uri;
|
||||
private String queryString;
|
||||
private String appId;
|
||||
private byte[] requestPayload;
|
||||
private String nonce;
|
||||
private long timestamp;
|
||||
private String aesSecretkey;
|
||||
|
||||
public static XbbSignatureInfo createGet() {
|
||||
return new XbbSignatureInfo().setHttpMethod("GET");
|
||||
}
|
||||
|
||||
public static XbbSignatureInfo createPost() {
|
||||
return new XbbSignatureInfo().setHttpMethod("POST");
|
||||
}
|
||||
|
||||
public String toCanonicalizedQueryString(String queryString) {
|
||||
if (StrUtil.isBlank(queryString)) {
|
||||
return "";
|
||||
}
|
||||
UrlQuery urlQuery = UrlQuery.of(queryString, StandardCharsets.UTF_8);
|
||||
Map<CharSequence, CharSequence> queryMap = urlQuery.getQueryMap();
|
||||
TreeMap<String, String> sortedMap = new TreeMap<>();
|
||||
queryMap.forEach((k, v) -> sortedMap.put(k.toString(), v.toString()));
|
||||
return new UrlQuery(sortedMap, true).build(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public String toPayloadStr() {
|
||||
if (ArrayUtil.isEmpty(requestPayload)) {
|
||||
return "";
|
||||
}
|
||||
return new Digester(DigestAlgorithm.SHA256).digestHex(requestPayload);
|
||||
}
|
||||
|
||||
public String toSignatureStr() {
|
||||
return httpMethod + '\n'
|
||||
+ uri + '\n'
|
||||
+ toCanonicalizedQueryString(queryString) + '\n'
|
||||
+ appId + '\n'
|
||||
+ toPayloadStr() + '\n'
|
||||
+ nonce + '\n'
|
||||
+ timestamp + '\n'
|
||||
+ aesSecretkey;
|
||||
}
|
||||
|
||||
|
||||
// 生成放在请求头的签名
|
||||
public String toSignature() {
|
||||
return new Digester(DigestAlgorithm.SHA256).digestHex(toSignatureStr());
|
||||
}
|
||||
|
||||
|
||||
// getter setter
|
||||
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public XbbSignatureInfo setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getHttpMethod() {
|
||||
return httpMethod;
|
||||
}
|
||||
|
||||
public XbbSignatureInfo setHttpMethod(String httpMethod) {
|
||||
this.httpMethod = httpMethod;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
public XbbSignatureInfo setUri(String uri) {
|
||||
this.uri = uri;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getQueryString() {
|
||||
return queryString;
|
||||
}
|
||||
|
||||
public XbbSignatureInfo setQueryString(String queryString) {
|
||||
this.queryString = queryString;
|
||||
return this;
|
||||
}
|
||||
|
||||
public byte[] getRequestPayload() {
|
||||
return requestPayload;
|
||||
}
|
||||
|
||||
public XbbSignatureInfo setRequestPayload(byte[] requestPayload) {
|
||||
this.requestPayload = requestPayload;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getNonce() {
|
||||
return nonce;
|
||||
}
|
||||
|
||||
public XbbSignatureInfo setNonce(String nonce) {
|
||||
this.nonce = nonce;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public XbbSignatureInfo setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getAesSecretkey() {
|
||||
return aesSecretkey;
|
||||
}
|
||||
|
||||
public XbbSignatureInfo setAesSecretkey(String aesSecretkey) {
|
||||
this.aesSecretkey = aesSecretkey;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user