diff --git a/pom.xml b/pom.xml index 8c16ca818..35c9b548e 100644 --- a/pom.xml +++ b/pom.xml @@ -419,6 +419,12 @@ ${revision} + + io.swagger + swagger-annotations + 1.6.2 + compile + diff --git a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java index 7fbc57f95..8ad7465ae 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java @@ -236,4 +236,7 @@ public class AuthController { return R.ok(result); } + + + } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CachePrefix.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CachePrefix.java new file mode 100644 index 000000000..d274d72ab --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CachePrefix.java @@ -0,0 +1,551 @@ +package org.dromara.common.core.constant; + + +/** + * 缓存前缀 + * + * @author pikachu + * @version 4.1 + * @since 1.0 + * 2018/3/19 + */ +public enum CachePrefix { + + + /** + * nonce + */ + NONCE, + + /** + * 在线人数 + */ + ONLINE_NUM, + + + /** + * 会员分布数据 + */ + MEMBER_DISTRIBUTION, + + /** + * 在线会员统计 + */ + ONLINE_MEMBER, + + /** + * token 信息 + */ + ACCESS_TOKEN, + /** + * token 信息 + */ + REFRESH_TOKEN, + /** + * 联合登录响应 + */ + CONNECT_RESULT, + /** + * 微信联合登陆 session key + */ + SESSION_KEY, + /** + * 权限 + */ + PERMISSION_LIST, + /** + * 部门id列表 + */ + DEPARTMENT_IDS, + + /** + * 用户错误登录限制 + */ + LOGIN_TIME_LIMIT, + /** + * 系统设置 + */ + SETTING, + + /** + * 验证码滑块源 + */ + VERIFICATION, + + /** + * 验证码滑块源 + */ + VERIFICATION_IMAGE, + + /** + * 快递平台 + */ + EXPRESS, + + /** + * 图片验证码 + */ + CAPTCHA, + + /** + * 商品 + */ + GOODS, + + /** + * 商品SKU + */ + GOODS_SKU, + + /** + * 运费模板脚本 + */ + SHIP_SCRIPT, + + /** + * 商品sku + */ + SKU, + + /** + * sku库存 + */ + SKU_STOCK, + + /** + * 促销商品sku库存 + */ + PROMOTION_GOODS_STOCK, + + /** + * 商品库存 + */ + GOODS_STOCK, + + /** + * 商品分类 树状结构 + */ + CATEGORY, + /** + * 商品分类 集合 + */ + CATEGORY_ARRAY, + /** + * 浏览次数 + */ + VISIT_COUNT, + /** + * 存储方案 + */ + UPLOADER, + /** + * 地区 + */ + REGION, + + /** + * 短信网关 + */ + SPlATFORM, + /** + * 短信验证码前缀 + */ + _CODE_PREFIX, + /** + * smtp + */ + SMTP, + /** + * 系统设置 + */ + SETTINGS, + /** + * 电子面单 + */ + WAYBILL, + /** + * 短信验证码 + */ + SMS_CODE, + /** + * 邮箱验证码 + */ + EMAIL_CODE, + /** + * 管理员角色权限对照表 + */ + ADMIN_URL_ROLE, + + /** + * 店铺管理员角色权限对照表 + */ + STORE_URL_ROLE, + + /** + * 手机验证标识 + */ + MOBILE_VALIDATE, + + /** + * 邮箱验证标识 + */ + EMAIL_VALIDATE, + + /** + * 店铺运费模版列表 + */ + SHIP_TEMPLATE, + + /** + * 店铺中某个运费模版 + */ + SHIP_TEMPLATE_ONE, + + //================促销================= + /** + * 促销活动 + */ + PROMOTION, + /** + * 促销活动 + */ + PROMOTION_GOODS, + + /*** 单品立减 */ + STORE_ID_MINUS, + + /*** 第二件半价 */ + STORE_ID_HALF_PRICE, + + /*** 满优惠 */ + STORE_ID_FULL_DISCOUNT, + + /** + * 秒杀活动活动缓存key前缀 + */ + STORE_ID_SECKILL, + + /** + * 团购活动缓存key前缀 + */ + STORE_ID_GROUP_BUY, + + /** + * 积分商品缓存key前缀 + */ + STORE_ID_EXCHANGE, + + + //================交易================= + + /** + * 购物车原始数据 + */ + CART_ORIGIN_DATA_PREFIX, + + /** + * 立即购买原始数据 + */ + BUY_NOW_ORIGIN_DATA_PREFIX, + + /** + * 交易原始数据 + */ + TRADE_ORIGIN_DATA_PREFIX, + + /** + * 立即购买sku + */ + CART_SKU_PREFIX, + + /** + * 购物车视图 + */ + CART_MEMBER_ID_PREFIX, + + /** + * 购物车,用户选择的促销信息 + */ + CART_PROMOTION_PREFIX, + + + /** + * 交易_交易价格的前缀 + */ + PRICE_SESSION_ID_PREFIX, + + /** + * 交易_交易单 + */ + TRADE_SESSION_ID_PREFIX, + + + /** + * 结算参数 + */ + CHECKOUT_PARAM_ID_PREFIX, + + /** + * 交易单号前缀 + */ + TRADE_SN_CACHE_PREFIX, + + /** + * 订单编号前缀 + */ + ORDER_SN_CACHE_PREFIX, + /** + * 订单编号标记 + */ + ORDER_SN_SIGN_CACHE_PREFIX, + /** + * 订单编号前缀 + */ + PAY_LOG_SN_CACHE_PREFIX, + + /** + * 合同编号 + */ + CONTRACT_SN_CACHE_PREFIX, + + + /** + * 零钱 + */ + SMALL_CHANGE_CACHE_PREFIX, + + /** + * 售后服务单号前缀 + */ + AFTER_SALE_SERVICE_PREFIX, + + /** + * 交易 + */ + TRADE, + + /** + * 站点导航栏 + */ + SITE_NAVIGATION, + + /** + * 支付参数 + */ + PAYMENT_CONFIG, + + /** + * 流程控制 + */ + FLOW, + + /** + * 热门搜索 + */ + HOT_WORD, + + /** + * 会员积分 + */ + MEMBER_POINT, + + /** + * 会员积分 + */ + POINT_ORDER, + + + /** + * 微博登录 + */ + WEIBO_STATE, + /** + * 微博登录 + */ + QQ_STATE, + /** + * 微博登录 + */ + GITHUB_STATE, + /** + * 验证码key + */ + VERIFICATION_KEY, + /** + * 验证码验证结果 + */ + VERIFICATION_RESULT, + /** + * 微信CGItoken + */ + WECHAT_CGI_ACCESS_TOKEN, + /** + * 微信JSApitoken + */ + WECHAT_JS_API_TOKEN, + /** + * 微信会话信息 + */ + WECHAT_SESSION_PARAMS, + /** + * 第三方用户权限 + */ + ALIPAY_CONFIG, + /** + * 微信支付配置 + */ + WECHAT_PAY_CONFIG, + /** + * 微信支付平台证书配置 + */ + WECHAT_PLAT_FORM_CERT, + /** + * 第三方用户权限 + */ + CONNECT_AUTH, + /** + * 平台PageView 统计 + */ + PV, + /** + * 平台UserView 统计 + */ + UV, + /** + * 平台 商品PV 统计 + */ + GOODS_PV, + /** + * 平台 商品UV 统计 + */ + GOODS_UV, + /** + * 店铺PageView 统计 + */ + STORE_PV, + /** + * 店铺UserView 统计 + */ + STORE_UV, + /** + * 店铺 商品PV 统计 + */ + STORE_GOODS_PV, + /** + * 店铺 商品UV 统计 + */ + STORE_GOODS_UV, + /** + * 分销员 + */ + DISTRIBUTION, + + /** + * 找回手机 + */ + FIND_MOBILE, + /** + * 文章分类 + */ + ARTICLE_CATEGORY, + /** + * 文章 + */ + ARTICLE_CACHE, + + /** + * 初始化索引 + */ + INIT_INDEX_PROCESS, + + /** + * 初始化索引标示 + */ + INIT_INDEX_FLAG, + + /** + * 店铺分类 + */ + STORE_CATEGORY, + /** + * 用户菜单 + */ + MENU_USER_ID, + /** + * 用户菜单 + */ + USER_MENU, + /** + * 订单暂时缓存 + */ + ORDER, + /** + * 敏感词 + */ + SENSITIVE, + /** + * 用户 UserSig 缓存前缀 + */ + USER_SIG("user:sig:"), + /** + * 页面 + */ + PAGE, + /** + * 文章缓存 + */ + ARTICLE("ARTICLE:"), + + /** + * 会员足迹 + */ + FOOTPRINT; + + private String prefix; + + CachePrefix(String prefix) { + this.prefix = prefix; + } + + CachePrefix() { + this.prefix = this.name() + "_"; + } + + public String getPrefix1() { + return prefix; + } + + public static String removePrefix(String str) { + return str.substring(str.lastIndexOf("}_") + 2); + } + + /** + * 通用获取缓存key值 + * + * @return 缓存key值 + */ + public String getPrefix() { + return "{" + this.name() + "}_"; + } + +// /** +// * 通用获取缓存key值 +// * +// * @param typeEnum 促销枚举 +// * @return 缓存key值 +// */ +// public String getPrefix(PromotionTypeEnum typeEnum) { +// return "{" + this.name() + "_" + typeEnum.name() + "}_"; +// } +// +// /** +// * 获取缓存key值 + 用户端 +// * 例如:三端都有用户体系,需要分别登录,如果用户名一致,则redis中的权限可能会冲突出错 +// * +// * @param user 角色 +// * @return 缓存key值 + 用户端 +// */ +// public String getPrefix(UserEnums user) { +// return "{" + this.name() + "_" + user.name() + "}_"; +// } +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/ResultCode.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/ResultCode.java new file mode 100644 index 000000000..eef30e94c --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/ResultCode.java @@ -0,0 +1,651 @@ +package org.dromara.common.core.constant; + +/** + * 返回状态码 + * 第一位 1:商品;2:用户;3:交易,4:促销,5:店铺,6:页面,7:设置,8:其他 + * + * @author Chopper + * @since 2020/4/8 1:36 下午 + */ +public enum ResultCode { + REGION_ALREADY_HAS_AGENT(100,"区域为空"), + + /** + * 成功状态码 + */ + SUCCESS(200, "成功"), + + /** + * 失败返回码 + */ + ERROR(400, "服务器繁忙,请稍后重试"), + + /** + * 失败返回码 + */ + DEMO_SITE_EXCEPTION(4001, "演示站点禁止使用"), + /** + * 参数异常 + */ + PARAMS_ERROR(4002, "参数异常"), + + + /** + * 系统异常 + */ + WECHAT_CONNECT_NOT_EXIST(1001, "微信联合登录未配置"), + VERIFICATION_EXIST(1002, "验证码服务异常"), + LIMIT_ERROR(1003, "访问过于频繁,请稍后再试"), + ILLEGAL_REQUEST_ERROR(1004, "非法请求,请重新刷新页面操作"), + IMAGE_FILE_EXT_ERROR(1005, "不支持图片格式"), + FILE_NOT_EXIST_ERROR(1011, "上传文件不能为空"), + FILE_TYPE_NOT_SUPPORT(1010, "不支持上传的文件类型!"), + PLATFORM_NOT_SUPPORTED_IM(1006, "平台未开启IM"), + STORE_NOT_SUPPORTED_IM(1007, "店铺未开启IM"), + UNINITIALIZED_PASSWORD(1008, "非初始化密码,无法进行初始化设置"), + FILE_DIRECTORY_NOT_EMPTY(1012, "文件夹下有文件,请删除所有文件后删除文件夹!"), + /** + * 分类 + */ + CATEGORY_NOT_EXIST(10001, "商品分类不存在"), + CATEGORY_NAME_IS_EXIST(10002, "该分类名称已存在"), + CATEGORY_PARENT_NOT_EXIST(10003, "该分类名称已存在"), + CATEGORY_BEYOND_THREE(10004, "最多为三级分类,添加失败"), + CATEGORY_HAS_CHILDREN(10005, "此类别下存在子类别不能删除"), + CATEGORY_HAS_GOODS(10006, "此类别下存在商品不能删除"), + CATEGORY_SAVE_ERROR(10007, "此类别下存在商品不能删除"), + CATEGORY_PARAMETER_NOT_EXIST(10012, "分类绑定参数组不存在"), + CATEGORY_PARAMETER_SAVE_ERROR(10008, "分类绑定参数组添加失败"), + CATEGORY_PARAMETER_UPDATE_ERROR(10009, "分类绑定参数组添加失败"), + CATEGORY_DELETE_FLAG_ERROR(10010, "子类状态不能与父类不一致!"), + CATEGORY_COMMISSION_RATE_ERROR(10011, "分类的佣金不正确!"), + + /** + * 商品 + */ + GOODS_ERROR(11001, "商品异常,请稍后重试"), + GOODS_NOT_EXIST(11001, "商品已下架"), + GOODS_NAME_ERROR(11002, "商品名称不正确,名称应为2-50字符"), + GOODS_UNDER_ERROR(11003, "商品下架失败"), + GOODS_UPPER_ERROR(11004, "商品上架失败"), + GOODS_AUTH_ERROR(11005, "商品审核失败"), + POINT_GOODS_ERROR(11006, "积分商品业务异常,请稍后重试"), + POINT_GOODS_NOT_EXIST(11020, "积分商品不存在"), + POINT_GOODS_CATEGORY_EXIST(11021, "当前积分商品分类已存在"), + GOODS_SKU_SN_ERROR(11007, "商品SKU货号不能为空"), + GOODS_SKU_PRICE_ERROR(11008, "商品SKU价格不能小于等于0"), + GOODS_SKU_COST_ERROR(11009, "商品SKU成本价不能小于等于0"), + GOODS_SKU_WEIGHT_ERROR(11010, "商品重量不能为负数"), + GOODS_SKU_QUANTITY_ERROR(11011, "商品库存数量不能为负数"), + GOODS_SKU_QUANTITY_NOT_ENOUGH(11011, "商品库存不足"), + MUST_HAVE_GOODS_SKU(11012, "规格必须要有一个!"), + MUST_HAVE_SALES_MODEL(11022, "销售模式为批发时必须要有批发规则!"), + + HAVE_INVALID_SALES_MODEL(11023, "批发规则存在小于等于0的无效数据!"), + MUST_HAVE_GOODS_SKU_VALUE(11024, "规格值不能为空!"), + DO_NOT_MATCH_WHOLESALE(11025, "批发商品购买数量不能低于起拍量!"), + GOODS_NOT_ERROR(11026, "商品不存在"), + + GOODS_PARAMS_ERROR(11013, "商品参数错误,刷新后重试"), + PHYSICAL_GOODS_NEED_TEMP(11014, "实物商品需选择配送模板"), + VIRTUAL_GOODS_NOT_NEED_TEMP(11015, "虚拟商品无需选择配送模板"), + GOODS_NOT_EXIST_STORE(11017, "当前用户无权操作此商品"), + GOODS_TYPE_ERROR(11016, "需选择商品类型"), + GOODS_STOCK_IMPORT_ERROR(11018, "导入商品库存失败,请检查表格数据"), + + /** + * 参数 + */ + PARAMETER_SAVE_ERROR(12001, "参数添加失败"), + PARAMETER_UPDATE_ERROR(12002, "参数编辑失败"), + + /** + * 规格 + */ + SPEC_SAVE_ERROR(13001, "规格修改失败"), + SPEC_UPDATE_ERROR(13002, "规格修改失败"), + SPEC_DELETE_ERROR(13003, "分类已经绑定此规格,请先解除关联"), + + /** + * 品牌 + */ + BRAND_SAVE_ERROR(14001, "品牌添加失败"), + BRAND_UPDATE_ERROR(14002, "品牌修改失败"), + BRAND_DISABLE_ERROR(14003, "品牌禁用失败"), + BRAND_DELETE_ERROR(14004, "品牌删除失败"), + BRAND_NAME_EXIST_ERROR(20002, "品牌名称重复!"), + BRAND_USE_DISABLE_ERROR(20003, "分类已经绑定品牌,请先解除关联"), + BRAND_BIND_GOODS_ERROR(20005, "品牌已经绑定商品,请先解除关联"), + BRAND_NOT_EXIST(20004, "品牌不存在"), + + /** + * 用户 + */ + USER_EDIT_SUCCESS(20001, "用户修改成功"), + USER_NOT_EXIST(20002, "用户不存在"), + USER_NOT_LOGIN(20003, "用户未登录"), + USER_AUTH_EXPIRED(20004, "用户已退出,请重新登录"), +// USER_AUTH_EXPIRE(408, "账号已被其他设备登录"), + USER_AUTHORITY_ERROR(20005, "权限不足"), + USER_CONNECT_LOGIN_ERROR(20006, "未找到登录信息"), + USER_EXIST(20008, "该用户名或手机号已被注册"), + USER_PHONE_NOT_EXIST(20009, "手机号不存在"), + USER_PASSWORD_ERROR(20010, "密码不正确"), + USER_NOT_PHONE(20011, "非当前用户的手机号"), + USER_CONNECT_ERROR(20012, "联合第三方登录,授权信息错误"), + USER_RECEIPT_REPEAT_ERROR(20013, "会员发票信息重复"), + USER_RECEIPT_NOT_EXIST(20014, "会员发票信息不存在"), + USER_EDIT_ERROR(20015, "用户修改失败"), + USER_OLD_PASSWORD_ERROR(20016, "旧密码不正确"), + USER_COLLECTION_EXIST(20017, "无法重复收藏"), + USER_GRADE_IS_DEFAULT(20018, "会员等级为默认会员等级"), + USER_NOT_BINDING(20020, "未绑定用户"), + USER_AUTO_REGISTER_ERROR(20021, "自动注册失败,请稍后重试"), + USER_OVERDUE_CONNECT_ERROR(20022, "授权信息已过期,请重新授权/登录"), + USER_CONNECT_BANDING_ERROR(20023, "当前联合登陆方式,已绑定其他账号,需进行解绑操作"), + USER_CONNECT_NOT_EXIST_ERROR(20024, "暂无联合登陆信息,无法实现一键注册功能,请点击第三方登录进行授权"), + USER_POINTS_ERROR(20024, "用户积分不足"), + CLERK_SUPPER(20025, "店主无法操作"), + CLERK_SAVE_ERROR(20026, "店员保存失败"), + CLERK_NOT_FOUND_ERROR(20027, "店员不存在"), + USER_STATUS_ERROR(20028, "用户已禁用"), + CLERK_USER_ERROR(20029, "此账户已经绑定其他店铺"), + CLERK_ALREADY_EXIT_ERROR(20030, "店员已经存在"), + CLERK_DISABLED_ERROR(20031, "店员已禁用"), + CLERK_CURRENT_SUPPER(20032, "无法删除当前登录店员"), + CANT_EDIT_CLERK_SHOPKEEPER(20033, "无法在店员管理编辑店员信息"), + USER_MOBILE_REPEATABLE_ERROR(20034, "该手机号已存在"), + /** + * 权限 + */ + PERMISSION_DEPARTMENT_ROLE_ERROR(21001, "角色已绑定部门,请逐个删除"), + PERMISSION_USER_ROLE_ERROR(21002, "角色已绑定管理员,请逐个删除"), + PERMISSION_MENU_ROLE_ERROR(21003, "菜单已绑定角色,请先删除或编辑角色"), + PERMISSION_DEPARTMENT_DELETE_ERROR(21004, "部门已经绑定管理员,请先删除或编辑管理员"), + PERMISSION_BEYOND_TEN(21005, "最多可以设置10个角色"), + PERMISSION_NOT_FOUND_ERROR(21006, "部门不存在"), + PERMISSION_ROLE_NOT_FOUND_ERROR(21007, "角色不存在"), + PERMISSION_CLERK_BAND_ERROR(21008, "此手机号码已绑定其他店铺 "), + + + /** + * 分销 + */ + DISTRIBUTION_CLOSE(22000, "分销功能关闭"), + DISTRIBUTION_NOT_EXIST(22001, "分销员不存在"), + DISTRIBUTION_IS_APPLY(22002, "分销员已申请,无需重复提交"), + DISTRIBUTION_AUDIT_ERROR(22003, "审核分销员失败"), + DISTRIBUTION_RETREAT_ERROR(22004, "分销员清退失败"), + DISTRIBUTION_CASH_NOT_EXIST(22005, "分销员提现记录不存在"), + DISTRIBUTION_GOODS_DOUBLE(22006, "不能重复添加分销商品"), + DISTRIBUTION_EDIT_ERROR(22007, "修改分销员失败"), + + /** + * 购物车 + */ + CART_ERROR(30001, "读取结算页的购物车异常"), + CART_NUM_ERROR(30010, "购买数量必须大于0"), + CART_PINTUAN_NOT_EXIST_ERROR(30002, "拼团活动已关闭,请稍后重试"), + CART_PINTUAN_LIMIT_ERROR(30003, "购买数量超过拼团活动限制数量"), + SHIPPING_NOT_APPLY(30005, "购物商品不支持当前收货地址配送"), + + /** + * 订单 + */ + ORDER_ERROR(31001, "创建订单异常,请稍后重试"), + ORDER_NOT_EXIST(31002, "订单不存在"), + ORDER_DELIVERED_ERROR(31003, "订单状态错误,无法进行确认收货"), + ORDER_UPDATE_PRICE_ERROR(31004, "已支付的订单不能修改金额"), + ORDER_LOGISTICS_ERROR(31005, "物流错误"), + ORDER_DELIVER_ERROR(31006, "物流错误"), + ORDER_NOT_USER(31007, "非当前会员的订单"), + ORDER_TAKE_ERROR(31008, "当前订单无法核销"), + MEMBER_ADDRESS_NOT_EXIST(31009, "订单无收货地址,请先配置收货地址"), + STORE_ADDRESS_NOT_EXIST(31009, "订单没有自提地址,请先选择自提地址"), + ORDER_DELIVER_NUM_ERROR(31010, "没有待发货的订单"), + ORDER_NOT_SUPPORT_DISTRIBUTION(31011, "购物车中包含不支持配送的商品,请重新选择收货地址,或者重新选择商品"), + ORDER_NOT_EXIST_VALID(31041, "购物车中无有效商品,请检查购物车内商品,或者重新选择商品"), + ORDER_CAN_NOT_CANCEL(31012, "当前订单状态不可取消"), + ORDER_BATCH_DELIVER_ERROR(31013, "批量发货,文件读取失败"), + ORDER_ITEM_NOT_EXIST(31014, "当前订单项不存在!"), + POINT_NOT_ENOUGH(31015, "当前会员积分不足购买当前积分商品!"), + ORDER_LABEL_ORDER_ERROR(31016, "订单不能打印电子面单"), + ORDER_PRICE_ERROR(31017,"订单金额不能小于等于0"), + ORDER_PACKAGE_NOT_EXIST(31017, "当前订单包裹不存在!"), + + + /** + * 支付 + */ + PAY_UN_WANTED(32000, "当前订单不需要付款,返回订单列表等待系统订单出库即可"), + PAY_SUCCESS(32001, "支付成功"), + PAY_INCONSISTENT_ERROR(32002, "付款金额和应付金额不一致"), + PAY_DOUBLE_ERROR(32003, "订单已支付,不能再次进行支付"), + PAY_CASHIER_ERROR(32004, "收银台信息获取错误"), + PAY_ERROR(32005, "支付业务异常,请稍后重试"), + PAY_BAN(32006, "当前订单不需要付款,请返回订单列表重新操作"), + PAY_PARTIAL_ERROR(32007, "该订单已部分支付,请前往订单中心进行支付"), + PAY_NOT_SUPPORT(32008, "支付暂不支持"), + PAY_CLIENT_TYPE_ERROR(32009, "错误的客户端"), + PAY_POINT_ENOUGH(32010, "积分不足,不能兑换"), + PAY_NOT_EXIST_ORDER(32011, "支付订单不存在"), + CAN_NOT_RECHARGE_WALLET(32012, "不能使用余额进行充值"), + RECHARGE_PRICE_ERROR(32013, "充值金额错误"), + + /** + * 售后 + */ + AFTER_SALES_NOT_PAY_ERROR(33001, "当前订单未支付,不能申请售后"), + AFTER_SALES_CANCEL_ERROR(33002, "当前售后单无法取消"), + AFTER_SALES_BAN(33003, "订单状态不允许申请售后,请联系平台或商家"), + AFTER_SALES_DOUBLE_ERROR(33004, "售后已审核,无法重复操作"), + AFTER_SALES_LOGISTICS_ERROR(33005, "物流公司错误,请重新选择"), + AFTER_STATUS_ERROR(33006, "售后状态错误,请刷新页面"), + RETURN_MONEY_OFFLINE_BANK_ERROR(33007, "当账号类型为银行转账时,银行信息不能为空"), + AFTER_SALES_PRICE_ERROR(33004, "申请退款金额错误"), + AFTER_GOODS_NUMBER_ERROR(33008, "申请售后商品数量错误"), + + /** + * 投诉 + */ + COMPLAINT_ORDER_ITEM_EMPTY_ERROR(33100, "订单不存在"), + COMPLAINT_SKU_EMPTY_ERROR(33101, "商品已下架,如需投诉请联系平台客服"), + COMPLAINT_ERROR(33102, "投诉异常,请稍后重试"), + COMPLAINT_NOT_EXIT(33103, "当前投诉记录不存在"), + COMPLAINT_ARBITRATION_RESULT_ERROR(33104, "结束订单投诉时,仲裁结果不能为空"), + COMPLAINT_APPEAL_CONTENT_ERROR(33105, "商家申诉时,申诉内容不能为空"), + COMPLAINT_CANCEL_ERROR(33106, "申诉已完成,不需要进行取消申诉操作"), + + + /** + * 余额 + */ + WALLET_NOT_EXIT_ERROR(34000, "钱包不存在,请联系管理员"), + WALLET_INSUFFICIENT(34001, "余额不足以支付订单,请充值!"), + WALLET_WITHDRAWAL_INSUFFICIENT(34002, "可提现金额不足!"), + WALLET_WITHDRAWAL_FROZEN_AMOUNT_INSUFFICIENT(34006, "冻结金额不足,无法处理提现申请请求!"), + WALLET_ERROR_INSUFFICIENT(34003, "零钱提现失败!"), + WALLET_REMARK_ERROR(34004, "请填写审核备注!"), + WALLET_EXIT_ERROR(34005, "钱包已存在,无法重复创建"), + WALLET_APPLY_ERROR(34006, "提现申请异常!"), + WALLET_APPLY_MIN_PRICE_ERROR(34007, "提现最低提现金额错误!"), + WALLET_WITHDRAWAL_AMOUNT_ERROR(34008, "申请提现金额异常!"), + /** + * 评价 + */ + EVALUATION_DOUBLE_ERROR(35001, "无法重复提交评价"), + + /** + * 活动 + */ + PROMOTION_GOODS_NOT_EXIT(40000, "当前促销商品不存在!"), + PROMOTION_GOODS_QUANTITY_NOT_EXIT(40020, "当前促销商品库存不足!"), + PROMOTION_GOODS_DO_NOT_JOIN_WHOLESALE(40050, "批发商品无法参加促销"), + PROMOTION_SAME_ACTIVE_EXIST(40001, "活动时间内已存在同类活动,请选择关闭、删除当前时段的活动"), + PROMOTION_START_TIME_ERROR(40002, "活动起始时间不能小于当前时间"), + PROMOTION_END_TIME_ERROR(40003, "活动结束时间不能小于当前时间"), + PROMOTION_TIME_ERROR(40004, "活动起始时间必须大于结束时间"), + PROMOTION_TIME_NOT_EXIST(40011, "活动起始时间和活动结束时间不能为空"), + PROMOTION_SAME_ERROR(40005, "当前时间段已存在相同活动!"), + PROMOTION_GOODS_ERROR(40006, "请选择要参与活动的商品"), + PROMOTION_STATUS_END(40007, "当前活动已停止"), + PROMOTION_UPDATE_ERROR(40008, "当前活动已开始/结束,无法编辑!"), + PROMOTION_ACTIVITY_GOODS_ERROR(40009, "当前活动已经开始无法添加商品"), + PROMOTION_ACTIVITY_ERROR(400010, "当前促销活动不存在"), + PROMOTION_LOG_EXIST(40011, "活动已参加,已发重复参加"), + APPLY_END_TIME_ERROR(40012, "参与截至时间不能小于当前时间,不能大于活动开始时间"), + + /** + * 优惠券 + */ + COUPON_LIMIT_ERROR(41000, "超出领取限制"), + COUPON_EDIT_STATUS_SUCCESS(41001, "修改状态成功!"), + COUPON_CANCELLATION_SUCCESS(41002, "会员优惠券作废成功"), + COUPON_EXPIRED(41003, "优惠券已使用/已过期,不能使用"), + COUPON_EDIT_STATUS_ERROR(41004, "优惠券修改状态失败!"), + COUPON_RECEIVE_ERROR(41005, "当前优惠券已经被领取完了,下次要早点来哦"), + COUPON_NUM_INSUFFICIENT_ERROR(41006, "优惠券剩余领取数量不足"), + COUPON_NOT_EXIST(41007, "当前优惠券不存在"), + COUPON_LIMIT_NUM_LESS_THAN_0(41008, "领取限制数量不能为负数"), + COUPON_LIMIT_GREATER_THAN_PUBLISH(41009, "领取限制数量超出发行数量"), + COUPON_DISCOUNT_ERROR(41010, "优惠券折扣必须小于10且大于0"), + COUPON_SCOPE_TYPE_GOODS_ERROR(41011, "当前关联范围类型为指定商品时,商品列表不能为空"), + COUPON_SCOPE_TYPE_CATEGORY_ERROR(41012, "当前关联范围类型为部分商品分类时,范围关联的id不能为空"), + COUPON_SCOPE_TYPE_STORE_ERROR(41013, "当前关联范围类型为部分店铺分类时,范围关联的id不能为空"), + COUPON_SCOPE_ERROR(41014, "指定商品范围关联id无效!"), + COUPON_MEMBER_NOT_EXIST(41015, "没有当前会员优惠券"), + COUPON_MEMBER_STATUS_ERROR(41016, "当前会员优惠券已过期/作废无法变更状态!"), + COUPON_RANGE_ERROR(41017, "优惠券使用时间范围错误"), + + SPECIAL_CANT_USE(41019, "特殊商品不能使用优惠券,不能使用"), + + COUPON_SAVE_ERROR(41020, "保存优惠券失败"), + COUPON_DELETE_ERROR(41021, "删除优惠券失败"), + COUPON_ACTIVITY_NOT_EXIST(41022, "当前优惠券活动不存在"), + COUPON_ACTIVITY_SAVE_ERROR(41023, "保存优惠券活动失败"), + COUPON_ACTIVITY_MAX_NUM(41024, "优惠券活动赠券数量最多为5"), + + COUPON_DO_NOT_RECEIVER(41030, "当前优惠券不允许主动领取"), + + /** + * 拼团 + */ + PINTUAN_MANUAL_OPEN_SUCCESS(42001, "手动开启拼团活动成功"), + PINTUAN_MANUAL_CLOSE_SUCCESS(42002, "手动关闭拼团活动成功"), + PINTUAN_ADD_SUCCESS(42003, "添加拼团活动成功"), + PINTUAN_EDIT_SUCCESS(42004, "修改拼团活动成功"), + PINTUAN_DELETE_SUCCESS(42005, "删除拼团活动成功"), + PINTUAN_MANUAL_OPEN_ERROR(42006, "手动开启拼团活动失败"), + PINTUAN_MANUAL_CLOSE_ERROR(42007, "手动关闭拼团活动失败"), + PINTUAN_ADD_ERROR(42008, "添加拼团活动失败"), + PINTUAN_EDIT_ERROR(42009, "修改拼团活动失败"), + PINTUAN_EDIT_ERROR_ITS_OPEN(42019, "拼团活动已开启,无法修改拼团活动!"), + PINTUAN_DELETE_ERROR(42010, "删除拼团活动失败"), + PINTUAN_JOIN_ERROR(42011, "不能参与自己发起的拼团活动!"), + PINTUAN_LIMIT_NUM_ERROR(42012, "购买数量超过拼团活动限制数量!"), + PINTUAN_NOT_EXIST_ERROR(42013, "当前拼团活动不存在!"), + PINTUAN_GOODS_NOT_EXIST_ERROR(42014, "当前拼团商品不存在!"), + + /** + * 满额活动 + */ + FULL_DISCOUNT_EDIT_SUCCESS(43001, "修改满优惠活动成功"), + FULL_DISCOUNT_EDIT_DELETE(43002, "删除满优惠活动成功"), + FULL_DISCOUNT_MODIFY_ERROR(43003, "当前编辑的满优惠活动已经开始或者已经结束,无法修改"), + FULL_DISCOUNT_NOT_EXIST_ERROR(43004, "当前要操作的满优惠活动不存在!"), + FULL_DISCOUNT_WAY_ERROR(43005, "请选择一种优惠方式!"), + FULL_DISCOUNT_GIFT_ERROR(43006, "请选择赠品!"), + FULL_DISCOUNT_COUPON_TIME_ERROR(43007, "赠送的优惠券有效时间必须在活动时间之内"), + FULL_DISCOUNT_MONEY_ERROR(43008, "请填写满减金额"), + FULL_DISCOUNT_MONEY_GREATER_THAN_MINUS(43009, "满减金额不能大于优惠门槛"), + FULL_RATE_NUM_ERROR(43010, "请填写打折数值"), + + /** + * 直播 + */ + STODIO_GOODS_EXIST_ERROR(44001, "直播商品已存在"), + COMMODITY_ERROR(44002, "添加直播商品失败"), + + /** + * 秒杀 + */ + SECKILL_NOT_START_ERROR(45000, "今日没有限时抢购活动,请明天再来看看吧。"), + SECKILL_NOT_EXIST_ERROR(45001, "当前参与的秒杀活动不存在!"), + SECKILL_APPLY_NOT_EXIST_ERROR(45010, "当前参与的秒杀活动不存在!"), + SECKILL_UPDATE_ERROR(45002, "当前秒杀活动活动已经开始,无法修改!"), + SECKILL_PRICE_ERROR(45003, "活动价格不能大于商品原价"), + SECKILL_TIME_ERROR(45004, "时刻参数异常"), + SECKILL_DELETE_ERROR(45005, "该秒杀活动活动的状态不能删除"), + SECKILL_OPEN_ERROR(45010, "该秒杀活动活动的状态不能删除"), + SECKILL_CLOSE_ERROR(45006, "该秒杀活动活动的状态不能关闭"), + + + /** + * 优惠券活动 + */ + COUPON_ACTIVITY_START_TIME_ERROR(46001, "活动时间小于当前时间,不能进行编辑删除操作"), + COUPON_ACTIVITY_MEMBER_ERROR(46002, "指定精准发券则必须指定会员,会员不可以为空"), + COUPON_ACTIVITY_ITEM_ERROR(46003, "优惠券活动必须指定优惠券,不能为空"), + COUPON_ACTIVITY_ITEM_MUST_NUM_ERROR(46004, "优惠券活动最多指定10个优惠券"), + COUPON_ACTIVITY_ITEM_NUM_ERROR(46005, "赠券数量必须大于0"), + COUPON_ACTIVITY_ITEM_NUM_MAX_VALUE_2(46006, "赠券数量最大为2"), + + /** + * 其他促销 + */ + MEMBER_SIGN_REPEAT(47001, "请勿重复签到"), + POINT_GOODS_ACTIVE_STOCK_ERROR(47002, "活动库存数量不能高于商品库存"), + POINT_GOODS_ACTIVE_STOCK_INSUFFICIENT(47003, "积分商品库存不足"), + + /** + * 砍价活动 + */ + KANJIA_GOODS_ACTIVE_STOCK_ERROR(48001, "活动库存数量不能高于商品库存"), + KANJIA_GOODS_ACTIVE_PRICE_ERROR(48002, "最低购买金额不能高于商品金额"), + KANJIA_GOODS_ACTIVE_HIGHEST_PRICE_ERROR(48003, "最高砍价金额不能为0且不能超过商品金额"), + KANJIA_GOODS_ACTIVE_LOWEST_PRICE_ERROR(48004, "最低砍价金额不能为0且不能超过商品金额"), + KANJIA_GOODS_ACTIVE_HIGHEST_LOWEST_PRICE_ERROR(48005, "最低砍价金额不能高于最高砍价金额"), + KANJIA_GOODS_ACTIVE_SETTLEMENT_PRICE_ERROR(48006, "结算金额不能高于商品金额"), + KANJIA_GOODS_DELETE_ERROR(48007, "删除砍价商品异常"), + KANJIA_GOODS_UPDATE_ERROR(48012, "更新砍价商品异常"), + KANJIA_ACTIVITY_NOT_FOUND_ERROR(48008, "砍价记录不存在"), + KANJIA_ACTIVITY_LOG_MEMBER_ERROR(48009, "当前会员已经帮砍"), + KANJIA_ACTIVITY_MEMBER_ERROR(48010, "当前会员已经发起此砍价商品活动"), + KANJIA_ACTIVITY_NOT_PASS_ERROR(48011, "当前砍价未满足条件,不能进行购买"), + KANJIA_NUM_BUY_ERROR(48012, "砍价商品购买数量不正确"), + /** + * 店铺 + */ + + STORE_NOT_EXIST(50001, "此店铺不存在"), + STORE_NAME_EXIST_ERROR(50002, "店铺名称已存在!"), + STORE_APPLY_DOUBLE_ERROR(50003, "已经拥有店铺!"), + STORE_NOT_OPEN(50004, "该会员未开通店铺"), + STORE_NOT_LOGIN_ERROR(50005, "未登录店铺"), + STORE_CLOSE_ERROR(50006, "店铺关闭,请联系管理员"), + STORE_DELIVER_GOODS_ADDRESS(50007,"请填写商家发货地址"), + FREIGHT_TEMPLATE_NOT_EXIST(50010, "当前模版不存在"), + STORE_STATUS_ERROR(50011, "店铺在申请中或审核中,请勿重复操作"), + STORE_DELIVER_ADDRESS_EXIST(50012,"请填写发货地址"), + + /** + * 结算单 + */ + BILL_CHECK_ERROR(51001, "只有已出账结算单可以核对"), + BILL_COMPLETE_ERROR(51002, "只有已审核结算单可以支付"), + + /** + * 文章 + */ + ARTICLE_CATEGORY_NAME_EXIST(60001, "文章分类名称已存在"), + ARTICLE_CATEGORY_PARENT_NOT_EXIST(60002, "文章分类父分类不存在"), + ARTICLE_CATEGORY_BEYOND_TWO(60003, "最多为二级分类,操作失败"), + ARTICLE_CATEGORY_DELETE_ERROR(60004, "该文章分类下存在子分类,不能删除"), + ARTICLE_CATEGORY_HAS_ARTICLE(60005, "该文章分类下存在文章,不能删除"), + ARTICLE_CATEGORY_NO_DELETION(60007, "默认文章分类不能进行删除"), + ARTICLE_NO_DELETION(60008, "默认文章不能进行删除"), + + + /** + * 页面 + */ + PAGE_NOT_EXIST(61001, "页面不存在"), + PAGE_OPEN_DELETE_ERROR(61002, "当前页面为开启状态,无法删除"), + PAGE_DELETE_ERROR(61003, "当前页面为唯一页面,无法删除"), + PAGE_RELEASE_ERROR(61004, "页面已发布,无需重复提交"), + + /** + * 设置 + */ + SETTING_NOT_TO_SET(70001, "该参数不需要设置"), + ALIPAY_NOT_SETTING(70002, "支付宝支付未配置"), + ALIPAY_EXCEPTION(70003, "支付宝支付错误,请稍后重试"), + ALIPAY_PARAMS_EXCEPTION(70004, "支付宝参数异常"), + LOGISTICS_NOT_SETTING(70005, "您还未配置快递查询"), + LOGISTICS_CHECK_SETTING(70005, "操作失败,请检查您的快递鸟配置"), + ORDER_SETTING_ERROR(70006, "系统订单配置异常"), + ALI_SMS_SETTING_ERROR(70007, "您还未配置阿里云短信"), + SMS_SIGN_EXIST_ERROR(70008, "短信签名已存在"), + + /** + * 站内信 + */ + NOTICE_NOT_EXIST(80001, "当前消息模板不存在"), + NOTICE_ERROR(80002, "修改站内信异常,请稍后重试"), + NOTICE_SEND_ERROR(80003, "发送站内信异常,请检查系统日志"), + + + /** + * OSS + */ + OSS_NOT_EXIST(80101, "OSS未配置"), + OSS_EXCEPTION_ERROR(80102, "文件上传失败,请稍后重试"), + OSS_DELETE_ERROR(80103, "图片删除失败"), + + /** + * 验证码 + */ + VERIFICATION_SEND_SUCCESS(80201, "短信验证码,发送成功"), + VERIFICATION_ERROR(80202, "验证失败"), + VERIFICATION_CODE_INVALID(80204, "验证码已失效,请重新校验"), + VERIFICATION_SMS_CHECKED_ERROR(80210, "短信验证码错误,请重新校验"), + + /** + * 微信相关异常 + */ + WECHAT_CONNECT_NOT_SETTING(80300, "微信联合登陆信息未配置"), + WECHAT_PAYMENT_NOT_SETTING(80301, "微信支付信息未配置"), + WECHAT_QRCODE_ERROR(80302, "微信二维码生成异常"), + WECHAT_MP_MESSAGE_ERROR(80303, "微信小程序小消息订阅异常"), + WECHAT_JSAPI_SIGN_ERROR(80304, "微信JsApi签名异常"), + WECHAT_CERT_ERROR(80305, "证书获取失败"), + WECHAT_MP_MESSAGE_TMPL_ERROR(80306, "未能获取到微信模版消息id"), + WECHAT_ERROR(80307, "微信接口异常"), + APP_VERSION_EXIST(80307, "APP版本已存在"), + APP_VERSION_PARAM_ERROR(80308, "添加APP版本参数异常"), + // 未选择APP类型 + APP_VERSION_TYPE_ERROR(80308, "请选择有效的APP类型"), + + /** + * IM + */ + IM_MESSAGE_ADD_ERROR(80400,"IM消息发送错误"), + IM_MESSAGE_EDIT_ERROR(80400,"IM消息更新错误"), + + /** + * 其他 + */ + CUSTOM_WORDS_EXIST_ERROR(90000, "当前自定义分词已存在!"), + CUSTOM_WORDS_NOT_EXIST_ERROR(90001, "当前自定义分词不存在!"), + CUSTOM_WORDS_SECRET_KEY_ERROR(90002, "秘钥验证失败!"), + CONNECT_NOT_EXIST(90000, "登录方式不存在!"), + ELASTICSEARCH_INDEX_INIT_ERROR(90003, "索引初始化失败!"), + PURCHASE_ORDER_DEADLINE_ERROR(90004, "供求单,已超过报名截止时间"), + USER_ADD_ERROR(90005, "用户添加失败"), + INDEX_BUILDING(90005, "索引正在生成"), + /** + * 只有达人才能申生成分享吗 + */ + SHARE_CODE_NOT_MA(30005,"只有达人才能生成分享吗"), + /** + * 分享码不存在 + */ + SHARE_CODE_NOT_EXIST(30001, "分享码不存在"), + + /** + * 分享码已被使用 + */ + SHARE_CODE_ALREADY_USED(30002, "分享码已被使用"), + + /** + * 分享码已存在 + */ + SHARE_CODE_ALREADY_EXIST(30003, "分享码已存在"), + + /** + * 不能绑定自己的分享码 + */ + CANNOT_BIND_OWN_CODE(30004, "不能绑定自己的分享码"), + + /** + * 已绑定过这个分享码 + */ + ALREADY_BIND_THIS_CODE(30008, "已绑定过这个分享码"), + + /** + * 已绑定过其他达人 + */ + ALREADY_BIND_SHARE_CODE(30009, "已绑定过其他达人,不能重复绑定"), + + /** + * 分享码无效 + */ + SHARE_CODE_INVALID(30006, "分享码无效"), + EXPERT_NOT_EXIST(30010,"达人不存在"), + EXPERT_EXIST(3012,"达人已经存在"), + INVALID_CODE_OR_PHONE(3011,"无效的分享码或手机号格式"), + + /** + * 分享码已被绑定 + */ + SHARE_CODE_ALREADY_BIND(30007, "分享码已被绑定"), + + /** + * 分享码不能绑定自己 + */ + SHARE_CODE_CANNOT_BIND_SELF(500, "分享码不能绑定自己"), + + /** + * 只有达人可以生成邀请码 + */ + ONLY_EXPERT_CAN_GENERATE_CODE(500, "只有达人可以生成邀请码"), + + /** + * 达人不能绑定邀请码 + */ + EXPERT_CANNOT_BIND_CODE(500, "达人不能绑定邀请码"), + + /** + * 核销码不存在 + */ + VERIFICATION_CODE_NOT_EXIST(500, "核销码不存在"), + + /** + * 核销码已过期 + */ + VERIFICATION_CODE_EXPIRED(500, "核销码已过期"), + + /** + * 核销码已被使用 + */ + VERIFICATION_CODE_ALREADY_USED(500, "核销码已被使用"), + + /** + * 核销操作繁忙 + */ + VERIFICATION_OPERATION_BUSY(500, "核销操作繁忙,请稍后重试"), + + /** + * 订单状态错误 + */ + ORDER_STATUS_ERROR(500, "订单状态错误"), + + /** + * 订单类型错误 + */ + ORDER_TYPE_ERROR(500, "订单类型错误"), + + /** + * 订单已核销 + */ + ORDER_ALREADY_VERIFICATION(500, "订单已核销"); + +// /** +// * 订单不存在 +// */ +// ORDER_NOT_EXIST(400, "订单不存在") + +// /** +// * 订单项不存在 +// */ +// ORDER_ITEM_NOT_EXIST(400, "订单项不存在"); + + + private final Integer code; + private final String message; + + + ResultCode(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Integer code() { + return this.code; + } + + public String message() { + return this.message; + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/exception/ServiceException.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/exception/ServiceException.java index e9dc6ec9b..3d4ca7fb4 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/exception/ServiceException.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/exception/ServiceException.java @@ -1,6 +1,7 @@ package org.dromara.common.core.exception; import lombok.*; +import org.dromara.common.core.constant.ResultCode; import java.io.Serial; @@ -41,6 +42,10 @@ public final class ServiceException extends RuntimeException { this.message = message; this.code = code; } + public ServiceException(ResultCode resultCode) { + this.message = resultCode.message(); + this.code = resultCode.code(); + } @Override public String getMessage() { diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfig.java b/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfig.java index a4e921f23..97d06bfef 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfig.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfig.java @@ -65,15 +65,16 @@ public class SecurityConfig implements WebMvcConfigurer { } // 检查 header 与 param 里的 clientid 与 token 里的是否一致 - String headerCid = request.getHeader(LoginHelper.CLIENT_KEY); - String paramCid = ServletUtils.getParameter(LoginHelper.CLIENT_KEY); - String clientId = StpUtil.getExtra(LoginHelper.CLIENT_KEY).toString(); - if (!StringUtils.equalsAny(clientId, headerCid, paramCid)) { - // token 无效 - throw NotLoginException.newInstance(StpUtil.getLoginType(), - "-100", "客户端ID与Token不匹配", - StpUtil.getTokenValue()); - } + // TODO: 2025/6/4 暂时注释掉 用于后端postman测试 +// String headerCid = request.getHeader(LoginHelper.CLIENT_KEY); +// String paramCid = ServletUtils.getParameter(LoginHelper.CLIENT_KEY); +// String clientId = StpUtil.getExtra(LoginHelper.CLIENT_KEY).toString(); +// if (!StringUtils.equalsAny(clientId, headerCid, paramCid)) { +// // token 无效 +// throw NotLoginException.newInstance(StpUtil.getLoginType(), +// "-100", "客户端ID与Token不匹配", +// StpUtil.getTokenValue()); +// } // 有效率影响 用于临时测试 // if (log.isDebugEnabled()) { diff --git a/ruoyi-modules/ruoyi-auth/pom.xml b/ruoyi-modules/ruoyi-auth/pom.xml index 50fe53c6b..998dc4534 100644 --- a/ruoyi-modules/ruoyi-auth/pom.xml +++ b/ruoyi-modules/ruoyi-auth/pom.xml @@ -99,6 +99,23 @@ org.dromara ruoyi-common-sse + + org.dromara + ruoyi-member + + + + com.tencentcloudapi + tencentcloud-sdk-java + 3.1.322 + + + + + com.github.tencentyun + tls-sig-api-v2 + 2.0 + diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/controller/MemberBuyerController.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/controller/MemberBuyerController.java new file mode 100644 index 000000000..72d47f1dd --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/controller/MemberBuyerController.java @@ -0,0 +1,365 @@ +package com.wzj.soopin.auth.controller; + + + +import cn.hutool.json.JSONException; +import cn.hutool.json.JSONObject; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; +import com.wzj.soopin.auth.domain.dto.entity.enums.VerificationEnums; +import com.wzj.soopin.auth.util.TLSSigAPIv2; +import com.wzj.soopin.member.domain.bo.MemberEditDTO; +import org.dromara.common.core.constant.ResultCode; +import com.wzj.soopin.auth.enums.UserEnums; +import com.wzj.soopin.auth.service.IMemberService; +import com.wzj.soopin.auth.service.IVerificationService; +import com.wzj.soopin.auth.util.SmsUtil; +import com.wzj.soopin.member.domain.po.Member; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import jakarta.validation.constraints.NotNull; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.exception.ServiceException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + + +/** + + * 买家端,会员接口 + + * + + * @author Chopper + + * @since 2020/11/16 10:07 下午 + + */ + + +@RestController + +@Api(tags = "买家端,会员接口") + +@Slf4j +@RequestMapping("/buyer/passport/member") + +public class MemberBuyerController { + + + + @Autowired + + private IMemberService memberService; + + @Autowired + + private SmsUtil smsUtil; + + + @Autowired + + private IVerificationService verificationService; + +// @Autowired + +// private GenerateTestUserSig generateTestUserSig; + + + + // 腾讯云 SDKAppID 和密钥 + + private static final long SDKAPPID = 1600080789; // 替换为您的 SDKAppID + + private static final String SECRETKEY = "311b5309d714a20f7f5b54360ee21b1e24ec208ebcd25ce8f47d24753bccc091"; // 替换为您的密钥 + + + + @ApiOperation(value = "登录接口") + + @ApiImplicitParams({ + + @ApiImplicitParam(name = "username", value = "用户名", required = true, paramType = "query"), + + @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query") + + }) + + @PostMapping("/userLogin") + + public R userLogin(@NotNull(message = "用户名不能为空") @RequestParam String username, + + @NotNull(message = "密码不能为空") @RequestParam String password, + + @RequestHeader String uuid) { + + verificationService.check(uuid, VerificationEnums.LOGIN); + + //return R.ok(this.memberService.usernameLogin(username, password)); + return R.ok(this.memberService.usernameLoginNew(username, password)); + + } + + + + @ApiOperation(value = "注销接口") + + @PostMapping("/logout") + + public R logout() { + + this.memberService.logout(UserEnums.MEMBER); + + return R.ok(); + + } + + @ApiOperation(value = "注销账号") + @PutMapping("/cancellation") + public R cancellation() { + memberService.cancellation(); + return R.ok(); + } + + + + @ApiOperation(value = "短信登录接口") + @ApiImplicitParams({ + @ApiImplicitParam(name = "mobile", value = "手机号", required = true, paramType = "query"), + @ApiImplicitParam(name = "code", value = "验证码", required = true, paramType = "query") + }) + @PostMapping("/smsLogin") + public R smsLogin(@NotNull(message = "手机号为空") @RequestParam String mobile, + @NotNull(message = "验证码为空") @RequestParam String code, + @RequestHeader String uuid) throws JSONException { + log.info("短信验证码校验成功: mobile={}, code={}", mobile, code); + return R.ok(memberService.mobilePhoneLoginNew(mobile)); + } + + + @SneakyThrows + @ApiOperation(value = "注册用户") + @ApiImplicitParams({ + @ApiImplicitParam(name = "username", value = "用户名", required = true, paramType = "query"), + @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query"), + @ApiImplicitParam(name = "mobilePhone", value = "手机号", required = true, paramType = "query"), + @ApiImplicitParam(name = "code", value = "验证码", required = true, paramType = "query") + }) + @PostMapping("/register") + public R register(@NotNull(message = "用户名不能为空") @RequestParam String username, + @NotNull(message = "密码不能为空") @RequestParam String password, + @NotNull(message = "手机号为空") @RequestParam String mobilePhone, + @RequestHeader String uuid, + @NotNull(message = "验证码不能为空") @RequestParam String code) { + // 检查用户名是否已存在 + if (memberService.usernameExists(username)) { + throw new ServiceException(ResultCode.ERROR); + } + + // 验证短信验证码 + if (!smsUtil.verifyCode(mobilePhone, VerificationEnums.REGISTER, uuid, code)) { + throw new ServiceException(ResultCode.VERIFICATION_SMS_CHECKED_ERROR); + } + + try { + // 生成 UserSig + TLSSigAPIv2 tlsSigAPIv2 = new TLSSigAPIv2(SDKAPPID, SECRETKEY); + long expire = TimeUnit.DAYS.toSeconds(365 * 50); // 设置为 50 年 + String userSig = tlsSigAPIv2.genUserSig(mobilePhone, expire); + String random = String.valueOf(System.currentTimeMillis()); + + // 构建腾讯云IM请求 + JSONObject requestBody = new JSONObject(); + requestBody.put("UserID", mobilePhone); + requestBody.put("Nick", username); + requestBody.put("FaceUrl", "http://www.qq.com"); + requestBody.put("Tag_Profile_IM_AllowType", "AllowType_Type_NeedConfirm"); + + String urlString = String.format("https://console.tim.qq.com/v4/im_open_login_svc/account_import?sdkappid=%s&identifier=%s&usersig=%s&random=%s&contenttype=json", + SDKAPPID, mobilePhone, userSig, random); + + OkHttpClient client = new OkHttpClient(); + Request request = new Request.Builder() + .url(urlString) +// .post(RequestBody.create(MediaType.get("application/json; charset=utf-8"), requestBody.toString())) + .build(); + + Response response = client.newCall(request).execute(); + if (!response.isSuccessful()) { + log.error("腾讯云IM账号导入失败: {}", response.body().string()); + throw new ServiceException(ResultCode.ERROR); + } + + // 注册用户 + return R.ok(memberService.registerNew(username, password, mobilePhone, userSig)); + } catch (Exception e) { + log.error("注册失败", e); + throw new ServiceException(ResultCode.ERROR); + } + } + + /*@PostMapping("/registerTest") + public R registerTest(){ + // 处理成功响应 + return R.ok(memberService.registerNew("leon", "12345678", "13899990000","qqqqqqqqqqqqqqqqqqqqqqq")); + }*/ + + + @ApiOperation(value = "获取当前登录用户接口") + @GetMapping + public R getUserInfo() { + return R.ok(memberService.getUserInfo()); + + } + + + + @ApiOperation(value = "通过短信重置密码") + + @ApiImplicitParams({ + + @ApiImplicitParam(name = "mobile", value = "手机号", required = true, paramType = "query"), + + @ApiImplicitParam(name = "password", value = "是否保存登录", required = true, paramType = "query") + + }) + + @PostMapping("/resetByMobile") + + public R resetByMobile(@NotNull(message = "手机号为空") @RequestParam String mobile, + + @NotNull(message = "验证码为空") @RequestParam String code, + + @RequestHeader String uuid) { + + //校验短信验证码是否正确 + + if (smsUtil.verifyCode(mobile, VerificationEnums.FIND_USER, uuid, code)) { + + //校验是否通过手机号可获取会员,存在则将会员信息存入缓存,有效时间3分钟 + + memberService.findByMobile(uuid, mobile); + + return R.ok(); + + } else { + + throw new ServiceException(ResultCode.VERIFICATION_SMS_CHECKED_ERROR); + + } + + } + + + + @ApiOperation(value = "修改密码") + + @ApiImplicitParams({ + + @ApiImplicitParam(name = "mobile", value = "手机号", required = true, paramType = "query"), + + @ApiImplicitParam(name = "password", value = "是否保存登录", required = true, paramType = "query") + + }) + + @PostMapping("/resetPassword") + + public R resetByMobile(@NotNull(message = "密码为空") @RequestParam String password, @RequestHeader String uuid) { + + + + return R.ok(memberService.resetByMobile(uuid, password)); + + } + + + + @ApiOperation(value = "修改用户自己资料") + + @PutMapping("/editOwn") + + public R editOwn(MemberEditDTO memberEditDTO) { + + + + return R.ok(memberService.editOwn(memberEditDTO)); + + } + + + + @ApiOperation(value = "修改密码") + + @ApiImplicitParams({ + + @ApiImplicitParam(name = "password", value = "旧密码", required = true, paramType = "query"), + + @ApiImplicitParam(name = "newPassword", value = "新密码", required = true, paramType = "query") + + }) + + @PutMapping("/modifyPass") + + public R modifyPass(@NotNull(message = "旧密码不能为空") @RequestParam String password, + + @NotNull(message = "新密码不能为空") @RequestParam String newPassword) { + + return R.ok(memberService.modifyPass(password, newPassword)); + + } + + + + + + @ApiOperation(value = "刷新token") + + @GetMapping("/refresh/{refreshToken}") + + public R refreshToken(@NotNull(message = "刷新token不能为空") @PathVariable String refreshToken) { + + return R.ok(this.memberService.refreshToken(refreshToken)); + + } + + + + @ApiOperation(value = "获取当前登录用户的IM信息") + @GetMapping("/im-info") + public R> getImInfo() { + // 获取当前登录用户 + Member member = memberService.getUserInfo(); + if (member == null) { + throw new ServiceException(ResultCode.USER_NOT_LOGIN); + } + + // 生成 UserSig + TLSSigAPIv2 tlsSigAPIv2 = new TLSSigAPIv2(SDKAPPID, SECRETKEY); + long expire = TimeUnit.DAYS.toSeconds(365 * 50); // 设置为 50 年 + String userSig = tlsSigAPIv2.genUserSig(member.getPhoneEncrypted(), expire); + + // 构建返回数据 + Map imInfo = new HashMap<>(); + imInfo.put("sdkAppId", SDKAPPID); + imInfo.put("userID", member.getPhoneEncrypted()); + imInfo.put("userSig", userSig); + imInfo.put("nickName", member.getNickname()); + imInfo.put("faceUrl", member.getAvatar() != null ? member.getAvatar() : "http://www.qq.com"); + + return R.ok(imInfo); + } + + + +} + + diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/bo/Token.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/bo/Token.java new file mode 100644 index 000000000..c63c6d310 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/bo/Token.java @@ -0,0 +1,67 @@ +package com.wzj.soopin.auth.domain.bo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Token 实体类 + * + * @author Chopper + * @version v1.0 2020-11-13 10:02 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Token { + /** + * 用户名 + */ + private String username; + + /** + * 访问token + */ + private String accessToken; + + /** + * 刷新token + */ + private String refreshToken; + + /** + * 认证用户信息 + */ + private Object authUser; + + /** + * 短视频系统账号信息 + */ + private String tikUser; + + /** + * 构造函数 + * + * @param accessToken 访问token + * @param refreshToken 刷新token + */ + public Token(String accessToken, String refreshToken) { + this.accessToken = accessToken; + this.refreshToken = refreshToken; + } + + /** + * 构造函数 + * + * @param username 用户名 + * @param accessToken 访问token + * @param refreshToken 刷新token + * @param authUser 认证用户信息 + */ + public Token(String username, String accessToken, String refreshToken, Object authUser) { + this.username = username; + this.accessToken = accessToken; + this.refreshToken = refreshToken; + this.authUser = authUser; + } +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/dto/VerificationDTO.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/dto/VerificationDTO.java new file mode 100644 index 000000000..03b3d27a2 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/dto/VerificationDTO.java @@ -0,0 +1,28 @@ +package com.wzj.soopin.auth.domain.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 验证码资源缓存DTO + * + * @author Chopper + * @since 2020/12/2 17:50 + */ +@Data +public class VerificationDTO implements Serializable { + + + /** + * 缓存资源 + */ + List verificationResources; + + /** + * 缓存滑块资源 + */ + List verificationSlider; + +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/dto/VerificationSource.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/dto/VerificationSource.java new file mode 100644 index 000000000..b448e4cc6 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/dto/VerificationSource.java @@ -0,0 +1,32 @@ +package com.wzj.soopin.auth.domain.dto; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.dromara.common.mybatis.core.domain.BaseEntity; + +/** + * 验证码资源维护 + * @author Chopper + * @since 2021/1/30 4:13 下午 + */ +@Data +@TableName("li_verification_source") +@ApiModel(value = "验证码资源维护") +public class VerificationSource extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "名称") + private String name; + + @ApiModelProperty(value = "资源地址") + private String resource; + + /** + * @see VerificationSourceEnum + */ + @ApiModelProperty(value = "验证码资源类型 SLIDER/SOURCE") + private String type; +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/dto/entity/enums/VerificationEnums.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/dto/entity/enums/VerificationEnums.java new file mode 100644 index 000000000..5481d2009 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/dto/entity/enums/VerificationEnums.java @@ -0,0 +1,26 @@ +package com.wzj.soopin.auth.domain.dto.entity.enums; + +/** + * VerificationEnums + * + * @author Chopper + * @version v1.0 + * 2020-12-22 19:11 + */ +public enum VerificationEnums { + + /** + * 登录 + * 注册 + * 找回用户 + * 修改密码 + * 支付钱包密码 + */ + LOGIN, + REGISTER, + FIND_USER, + UPDATE_PASSWORD, + WALLET_PASSWORD; +} + + diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/dto/entity/enums/VerificationSourceEnum.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/dto/entity/enums/VerificationSourceEnum.java new file mode 100644 index 000000000..05dec25d4 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/domain/dto/entity/enums/VerificationSourceEnum.java @@ -0,0 +1,25 @@ +package com.wzj.soopin.auth.domain.dto.entity.enums; + + +/** + * 验证码资源枚举 + * + * @author Chopper + * @since 2021/1/26 15:55 + */ +public enum VerificationSourceEnum { + /** + * 滑块 + */ + SLIDER("滑块"), + /** + * 验证码源 + */ + RESOURCE("验证码源"); + + private final String description; + + VerificationSourceEnum(String des) { + this.description = des; + } +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/enums/UserEnums.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/enums/UserEnums.java new file mode 100644 index 000000000..53f919f1c --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/enums/UserEnums.java @@ -0,0 +1,27 @@ +package com.wzj.soopin.auth.enums; + +/** + * token角色类型 + * + * @author Chopper + * @version v1.0 + * @since 2020/8/18 15:23 + */ +public enum UserEnums { + /** + * 角色 + */ + MEMBER("会员"), + STORE("商家"), + MANAGER("管理员"), + SYSTEM("系统"); + private final String role; + + UserEnums(String role) { + this.role = role; + } + + public String getRole() { + return role; + } +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/security/UserContext.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/security/UserContext.java new file mode 100644 index 000000000..14efceb6b --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/security/UserContext.java @@ -0,0 +1,97 @@ +package com.wzj.soopin.auth.security; + +import cn.hutool.jwt.Claims; +import com.google.gson.Gson; +import com.wzj.soopin.auth.enums.SecurityEnum; +import jakarta.servlet.http.HttpServletRequest; +import org.dromara.common.core.constant.ResultCode; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.redis.redis.RedisCache; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + + +/** + * 用户上下文 + * + * @author Chopper + * @version v4.0 + * @since 2020/11/14 20:27 + */ +public class UserContext { + + /** + * 根据request获取用户信息 + * + * @return 授权用户 + */ +// public static AuthUser getCurrentUser() { +// if (RequestContextHolder.getRequestAttributes() != null) { +// HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); +// String accessToken = request.getHeader(SecurityEnum.HEADER_TOKEN.getValue()); +// return getAuthUser(accessToken); +// } +// return null; +// } + + /** + * 根据request获取用户信息 + * + * @return 授权用户 + */ + public static String getUuid() { + if (RequestContextHolder.getRequestAttributes() != null) { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + return request.getHeader(SecurityEnum.UUID.getValue()); + } + return null; + } + + +// /** +// * 根据jwt获取token重的用户信息 +// * +// * @param cache 缓存 +// * @param accessToken token +// * @return 授权用户 +// */ +// public static AuthUser getAuthUser(RedisCache cache, String accessToken) { +// try { +// if (cache.keys("*" + accessToken).isEmpty()) { +// throw new ServiceException(ResultCode.USER_AUTHORITY_ERROR); +// } +// return getAuthUser(accessToken); +// } catch (Exception e) { +// return null; +// } +// } + + public static String getCurrentUserToken() { + if (RequestContextHolder.getRequestAttributes() != null) { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + return request.getHeader(SecurityEnum.HEADER_TOKEN.getValue()); + } + return null; + } + +// /** +// * 根据jwt获取token重的用户信息 +// * +// * @param accessToken token +// * @return 授权用户 +// */ +// public static AuthUser getAuthUser(String accessToken) { +// try { +// //获取token的信息 +// Claims claims +// = Jwts.parser() +// .setSigningKey(SecretKeyUtil.generalKeyByDecoders()) +// .parseClaimsJws(accessToken).getBody(); +// //获取存储在claims中的用户信息 +// String json = claims.get(SecurityEnum.USER_CONTEXT.getValue()).toString(); +// return new Gson().fromJson(json, AuthUser.class); +// } catch (Exception e) { +// return null; +// } +// } +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/IMemberService.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/IMemberService.java new file mode 100644 index 000000000..f7d441d75 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/IMemberService.java @@ -0,0 +1,295 @@ +package com.wzj.soopin.auth.service; + + + +import cn.hutool.json.JSONException; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.wzj.soopin.auth.domain.bo.Token; +import com.wzj.soopin.auth.enums.UserEnums; +import com.wzj.soopin.auth.vo.MemberSearchVO; +import com.wzj.soopin.member.domain.bo.MemberAddDTO; +import com.wzj.soopin.member.domain.bo.MemberEditDTO; +import com.wzj.soopin.member.domain.po.Member; +import com.wzj.soopin.member.domain.vo.MemberVO; +import org.dromara.common.core.domain.R; + +import java.util.List; +import java.util.Map; + +/** + * 会员业务层 + * + * @author Bulbasaur + * @since 2020-02-25 14:10:16 + */ +public interface IMemberService extends IService { + + boolean usernameExists(String username); // 确保这个方法在接口中定义 + + /** + * 获取当前登录的用户信息 + * + * @return 会员信息 + */ + Member getUserInfo(); + + /** + * 是否可以通过手机获取用户 + * + * @param uuid UUID + * @param mobile 手机号 + * @return 操作状态 + */ + boolean findByMobile(String uuid, String mobile); + + /** + * 通过用户名获取用户 + * + * @param username 用户名 + * @return 会员信息 + */ + Member findByUsername(String username); + + /** + * 登录:用户名、密码登录 + * + * @param username 用户名 + * @param password 密码 + * @return token + */ + Token usernameLogin(String username, String password); + + /** + * 商家登录:用户名、密码登录 + * + * @param username 用户名 + * @param password 密码 + * @return token + */ + Token usernameStoreLogin(String username, String password); + + /** + * 注册:手机号、验证码登录 + * + * @param mobilePhone 手机号 + * @return token + */ + Token mobilePhoneLogin(String mobilePhone); + + /** + * 修改会员信息 + * + * @param memberEditDTO 会员修改信息 + * @return 修改后的会员 + */ + Member editOwn(MemberEditDTO memberEditDTO); + + /** + * 修改用户密码 + * + * @param oldPassword 旧密码 + * @param newPassword 新密码 + * @return 操作结果 + */ + Member modifyPass(String oldPassword, String newPassword); + + /** + * 注册会员 + * + * @param userName 会员 + * @param password 密码 + * @param mobilePhone mobilePhone + * @return 处理结果 + */ + Token register(String userName, String password, String mobilePhone, String userSig); + + /** + * 修改当前会员的手机号 + * + * @param mobile 手机号 + * @return 操作结果 + */ + boolean changeMobile(String mobile); + + /** + * 通过手机号修改密码 + * + * @param mobile 手机号 + * @param password 密码 + * @return + */ + boolean resetByMobile(String mobile, String password); + + /** + * 后台-添加会员 + * + * @param memberAddDTO 会员 + * @return 会员 + */ + Member addMember(MemberAddDTO memberAddDTO); + +// /** +// * 后台-修改会员 +// * +// * @param managerMemberEditDTO 后台修改会员参数 +// * @return 会员 +// */ +// Member updateMember(ManagerMemberEditDTO managerMemberEditDTO); + + /** + * 获取会员分页 + * + * @param memberSearchVO 会员搜索VO + * @param page 分页 + * @return 会员分页 + */ + IPage getMemberPage(MemberSearchVO memberSearchVO, IPage page); + + /** + * 一键注册会员 + * + * @return + */ + Token autoRegister(); + +// /** +// * 一键注册会员 +// * +// * @param authUser 联合登录用户 +// * @return Token +// */ +// Token autoRegister(ConnectAuthUser authUser); + + /** + * 刷新token + * + * @param refreshToken + * @return Token + */ + Token refreshToken(String refreshToken); + + /** + * 刷新token + * + * @param refreshToken + * @return Token + */ + Token refreshStoreToken(String refreshToken); + + /** + * 会员积分变动 + * + * @param point 变动积分 + * @param type 是否增加积分 INCREASE 增加 REDUCE 扣减 + * @param memberId 会员id + * @param content 变动日志 + * @return 操作结果 + */ + Boolean updateMemberPoint(Long point, String type, String memberId, String content); + + /** + * 更新会员状态 + * + * @param memberIds 会员ID列表 + * @param disabled 是否禁用 + * @param banDays 封禁天数,如果为null则永久封禁 + * @return 操作结果代码 + */ + R updateMemberStatus(List memberIds, Boolean disabled, Integer banDays); + + /** + * 根据条件查询会员总数 + * + * @param memberSearchVO + * @return 会员总数 + */ + long getMemberNum(MemberSearchVO memberSearchVO); + + /** + * 获取指定会员数据 + * + * @param columns 指定获取的列 + * @param memberIds 会员ids + * @return 指定会员数据 + */ + List> listFieldsByMemberIds(String columns, List memberIds); + + /** + * 登出 + * + * @param userEnums token角色类型 + */ + void logout(UserEnums userEnums); + + + /** + * 注销账号 + * + * @return 操作结果 + */ + void cancellation(); + + /** + * 获取所有会员的手机号 + * + * @return 所有会员的手机号 + */ + List getAllMemberMobile(); + + /** + * 更新会员登录时间为最新时间 + * + * @param memberId 会员id + * @return 是否更新成功 + */ + boolean updateMemberLoginTime(String memberId); + + /** + * 获取用户VO + * + * @param id 会员id + * @return 用户VO + */ + MemberVO getMember(String id); + + /** + * 注册会员 + * + * @param userName 会员 + * @param password 密码 + * @param mobilePhone mobilePhone + * @return 处理结果 + */ + Token registerNew(String userName, String password, String mobilePhone, String userSig); + + /** + * 登录获取短视频系统账户信息 + * + * @param username + * @param password + * @return + */ + Token usernameLoginNew(String username, String password); + + /** + * 短信登录获取短视频系统账户信息 + * + * @param mobilePhone + * @return + */ + Token mobilePhoneLoginNew(String mobilePhone) throws JSONException; + + /** + * 设置会员为代理人 + * @param memberId 会员ID + * @param region 代理区域编码 + */ + void setMemberAsAgent(String memberId, String region); + + Member updateMemberS(Member member); + + void endsetMemberAsAgent(String memberId, String region); + + void updateRevenueSharingPercentage(String id, String percentage); +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/IVerificationService.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/IVerificationService.java new file mode 100644 index 000000000..f32840197 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/IVerificationService.java @@ -0,0 +1,44 @@ +package com.wzj.soopin.auth.service; + + +import com.wzj.soopin.auth.domain.dto.entity.enums.VerificationEnums; + +import java.io.IOException; +import java.util.Map; + +/** + * 验证码模块 + * + * @author Bulbasaur + * @since 2021/7/9 1:42 上午 + */ +public interface IVerificationService { + /** + * 获取校验对象 + * + * @param verificationEnums 校验枚举 + * @param uuid uuid + * @return 校验对象 + * @throws IOException 校验错误 + */ + Map createVerification(VerificationEnums verificationEnums, String uuid); + + /** + * 预校验 + * + * @param xPos 位移距离 + * @param uuid 用户唯一表示 + * @param verificationEnums 校验枚举 + * @return + */ + boolean preCheck(Integer xPos, String uuid, VerificationEnums verificationEnums); + + /** + * 验证码校验 + * + * @param uuid 用户唯一表示 + * @param verificationEnums 校验枚举 + * @return 操作结果 + */ + boolean check(String uuid, VerificationEnums verificationEnums); +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/IVerificationSourceService.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/IVerificationSourceService.java new file mode 100644 index 000000000..ff4c5a1c1 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/IVerificationSourceService.java @@ -0,0 +1,36 @@ +package com.wzj.soopin.auth.service; + + +import com.baomidou.mybatisplus.extension.service.IService; +import com.wzj.soopin.auth.domain.dto.VerificationDTO; +import com.wzj.soopin.auth.domain.dto.VerificationSource; +import org.dromara.common.core.constant.CachePrefix; + +/** + * 验证码资源维护 业务层 + * + * @author Chopper + * @since 2020/11/17 3:44 下午 + */ +public interface IVerificationSourceService extends IService { + + /** + * 缓存 + */ + String VERIFICATION_CACHE = CachePrefix.VERIFICATION.getPrefix(); + + + /** + * 初始化缓存 + * + * @return + */ + VerificationDTO initCache(); + + /** + * 获取验证缓存 + * + * @return 验证码 + */ + VerificationDTO getVerificationCache(); +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/impl/MemberServiceImpl.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/impl/MemberServiceImpl.java new file mode 100644 index 000000000..1c0296758 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/impl/MemberServiceImpl.java @@ -0,0 +1,1394 @@ +package com.wzj.soopin.auth.service.impl; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.json.JSONException; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.wzj.soopin.auth.domain.bo.Token; +import com.wzj.soopin.auth.enums.UserEnums; +import com.wzj.soopin.auth.service.IMemberService; +import com.wzj.soopin.auth.vo.MemberSearchVO; +import com.wzj.soopin.member.domain.bo.MemberAddDTO; +import com.wzj.soopin.member.domain.bo.MemberEditDTO; +import com.wzj.soopin.member.domain.po.Member; +import com.wzj.soopin.member.domain.vo.MemberVO; +import com.wzj.soopin.member.mapper.MemberMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.dromara.common.core.domain.R; +import org.dromara.common.redis.redis.RedisCache; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + + + +/** + * 会员接口业务层实现 + * + * @author Chopper + * @since 2021-03-29 14:10:16 + */ +@Slf4j +@Service +public class MemberServiceImpl extends ServiceImpl implements IMemberService { + @Autowired + private MemberMapper memberMapper; + + @Override + public boolean usernameExists(String username) { + return false; + } + + @Override + public Member getUserInfo() { + return null; + } + + @Override + public boolean findByMobile(String uuid, String mobile) { + return false; + } + + @Override + public Member findByUsername(String username) { + return null; + } + + @Override + public Token usernameLogin(String username, String password) { + return null; + } + + @Override + public Token usernameStoreLogin(String username, String password) { + return null; + } + + @Override + public Token mobilePhoneLogin(String mobilePhone) { + return null; + } + + @Override + public Member editOwn(MemberEditDTO memberEditDTO) { + return null; + } + + @Override + public Member modifyPass(String oldPassword, String newPassword) { + return null; + } + + @Override + public Token register(String userName, String password, String mobilePhone, String userSig) { + return null; + } + + @Override + public boolean changeMobile(String mobile) { + return false; + } + + @Override + public boolean resetByMobile(String mobile, String password) { + return false; + } + + @Override + public Member addMember(MemberAddDTO memberAddDTO) { + return null; + } + + @Override + public IPage getMemberPage(MemberSearchVO memberSearchVO, IPage page) { + return null; + } + + @Override + public Token autoRegister() { + return null; + } + + @Override + public Token refreshToken(String refreshToken) { + return null; + } + + @Override + public Token refreshStoreToken(String refreshToken) { + return null; + } + + @Override + public Boolean updateMemberPoint(Long point, String type, String memberId, String content) { + return null; + } + + @Override + public R updateMemberStatus(List memberIds, Boolean disabled, Integer banDays) { + return null; + } + + @Override + public long getMemberNum(MemberSearchVO memberSearchVO) { + return 0; + } + + @Override + public List> listFieldsByMemberIds(String columns, List memberIds) { + return null; + } + + @Override + public void logout(UserEnums userEnums) { + + } + + @Override + public void cancellation() { + + } + + @Override + public List getAllMemberMobile() { + return null; + } + + @Override + public boolean updateMemberLoginTime(String memberId) { + return false; + } + + @Override + public MemberVO getMember(String id) { + return null; + } + + @Override + public Token registerNew(String userName, String password, String mobilePhone, String userSig) { + return null; + } + + @Override + public Token usernameLoginNew(String username, String password) { + return null; + } + + @Override + public Token mobilePhoneLoginNew(String mobilePhone) throws JSONException { + return null; + } + + @Override + public void setMemberAsAgent(String memberId, String region) { + + } + + @Override + public Member updateMemberS(Member member) { + return null; + } + + @Override + public void endsetMemberAsAgent(String memberId, String region) { + + } + + @Override + public void updateRevenueSharingPercentage(String id, String percentage) { + + } + +// /** +// * 会员token +// */ +// @Autowired +// private MemberTokenGenerate memberTokenGenerate; +// /** +// * 商家token +// */ +// @Autowired +// private StoreTokenGenerate storeTokenGenerate; +// /** +// * 联合登录 +// */ +// @Autowired +// private ConnectService connectService; +// /** +// * 店铺 +// */ +// @Autowired +// private StoreService storeService; +// /** +// * RocketMQ 配置 +// */ +// @Autowired +// private RocketmqCustomProperties rocketmqCustomProperties; +// /** +// * RocketMQ +// */ +// @Autowired +// private RocketMQTemplate rocketMQTemplate; +// /** +// * 缓存 +// */ +// @Autowired +// private RedisCache cache; +// +// @Autowired +// private RevenueSharingMapper revenueSharingMapper; +// +// @Override +// public Member findByUsername(String userName) { +// QueryWrapper queryWrapper = new QueryWrapper<>(); +// queryWrapper.eq("username", userName); +// return this.baseMapper.selectOne(queryWrapper); +// } +// +// @Override +// public boolean usernameExists(String username) { +// return memberMapper.countByUsername(username) > 0; // 确保实现 +// } +// +// @Override +// public Member getUserInfo() { +// AuthUser tokenUser = UserContext.getCurrentUser(); +// if (tokenUser != null) { +// return this.findByUsername(tokenUser.getUsername()); +// } +// throw new ServiceException(ResultCode.USER_NOT_LOGIN); +// } +// +// @Override +// public boolean findByMobile(String uuid, String mobile) { +// QueryWrapper queryWrapper = new QueryWrapper<>(); +// queryWrapper.eq("mobile", mobile); +// Member member = this.baseMapper.selectOne(queryWrapper); +// if (member == null) { +// throw new ServiceException(ResultCode.USER_NOT_PHONE); +// } +// cache.put(CachePrefix.FIND_MOBILE + uuid, mobile, 300L); +// +// return true; +// } +// +// @Override +// public Token usernameLogin(String username, String password) { +// Member member = this.findMember(username); +// // 判断用户是否存在 +// if (member == null || !member.getDisabled()) { +// throw new ServiceException(ResultCode.USER_NOT_EXIST); +// } +//// // 判断密码是否输入正确 +//// if (!new BCryptPasswordEncoder().matches(password, member.getPassword())) { +//// throw new ServiceException(ResultCode.USER_PASSWORD_ERROR); +//// } +// loginBindUser(member); +// return memberTokenGenerate.createToken(member, false); +// } +// +// @Override +// public Token usernameStoreLogin(String username, String password) { +// +// Member member = this.findMember(username); +// +//// // 对输入的密码进行 MD5 哈希处理 +//// String hashedPassword = md5Hash(password); +// // 判断用户是否存在 +// if (member == null) { +// throw new ServiceException(ResultCode.USER_NOT_EXIST); +// } +// // 判断密码是否输入正确 +//// if (!new BCryptPasswordEncoder().matches(password, member.getPassword())) { +//// throw new ServiceException(ResultCode.USER_PASSWORD_ERROR); +//// } +// // 对店铺状态的判定处理 +// if (Boolean.TRUE.equals(member.getHaveStore())) { +// Store store = storeService.getById(member.getStoreId()); +// if (!store.getStoreDisable().equals(StoreStatusEnum.OPEN.name())) { +// throw new ServiceException(ResultCode.STORE_CLOSE_ERROR); +// } +// } else { +// throw new ServiceException(ResultCode.USER_NOT_EXIST); +// } +// +// return storeTokenGenerate.createToken(member, false); +// } +// +// private String md5Hash(String input) { +// try { +// // 获取 MD5 摘要算法的 MessageDigest 对象 +// MessageDigest md = MessageDigest.getInstance("MD5"); +// // 使用指定的字节数组更新摘要 +// md.update(input.getBytes()); +// // 获取密文 +// byte[] digest = md.digest(); +// StringBuilder sb = new StringBuilder(); +// for (byte b : digest) { +// sb.append(String.format("%02x", b & 0xff)); +// } +// return sb.toString(); +// } catch (NoSuchAlgorithmException e) { +// throw new RuntimeException(e); +// } +// } +// +// /** +// * 传递手机号或者用户名 +// * +// * @param userName 手机号或者用户名 +// * @return 会员信息 +// */ +// private Member findMember(String userName) { +// QueryWrapper queryWrapper = new QueryWrapper<>(); +// queryWrapper.eq("username", userName).or().eq("mobile", userName); +// return this.getOne(queryWrapper); +// } +// +// @Override +// public Token autoRegister(ConnectAuthUser authUser) { +// if (CharSequenceUtil.isEmpty(authUser.getNickname())) { +// authUser.setNickname("临时昵称"); +// } +// if (CharSequenceUtil.isEmpty(authUser.getAvatar())) { +// authUser.setAvatar("https://i.loli.net/2020/11/19/LyN6JF7zZRskdIe.png"); +// } +// try { +// String username = UuidUtils.getUUID(); +// Member member = new Member(username, UuidUtils.getUUID(), authUser.getAvatar(), authUser.getNickname(), +// authUser.getGender() != null ? Convert.toInt(authUser.getGender().getCode()) : 0); +// +// // 生成 UserSig +// String userSig = generateUserSig(username); +// member.setUserSig(userSig); +// +// // 创建 IM 账号 +// boolean imAccountCreated = createTencentIMAccount(username, userSig); +// if (!imAccountCreated) { +// log.error("创建IM账号失败,用户名: {}", username); +// throw new ServiceException(ResultCode.ERROR, "创建IM账号失败"); +// } +// +// registerHandler(member); +// // 绑定登录方式 +// loginBindUser(member); +// return memberTokenGenerate.createToken(member, false); +// } catch (ServiceException e) { +// log.error("自动注册服务泡出异常:", e); +// throw e; +// } catch (Exception e) { +// log.error("自动注册异常:", e); +// throw new ServiceException(ResultCode.USER_AUTO_REGISTER_ERROR); +// } +// } +// +// @Override +// public Token autoRegister() { +// ConnectAuthUser connectAuthUser = this.checkConnectUser(); +// return this.autoRegister(connectAuthUser); +// } +// +// @Override +// public Token refreshToken(String refreshToken) { +// return memberTokenGenerate.refreshToken(refreshToken); +// } +// +// @Override +// public Token refreshStoreToken(String refreshToken) { +// return storeTokenGenerate.refreshToken(refreshToken); +// } +// +// @Override +// public Token mobilePhoneLogin(String mobilePhone) { +// QueryWrapper queryWrapper = new QueryWrapper<>(); +// queryWrapper.eq("mobile", mobilePhone); +// Member member = this.baseMapper.selectOne(queryWrapper); +// // 如果手机号不存在则自动注册用户 +// if (member == null) { +// member = new Member(mobilePhone, UuidUtils.getUUID(), mobilePhone); +// +// // 直接设置默认密码 +// BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); +// member.setPassword(passwordEncoder.encode("123456")); +// +// registerHandler(member); +// log.info("手机号登录自动注册用户: {}, 默认密码: 123456", mobilePhone); +// } +// loginBindUser(member); +// return memberTokenGenerate.createToken(member, false); +// } +// +// /** +// * 注册方法抽象 +// * +// * @param member +// */ +// private void registerHandler(Member member) { +// member.setId(SnowFlake.getIdStr()); +// +// // 确保所有注册会员都使用默认密码123456 +// BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); +// String encodedPassword = passwordEncoder.encode("123456"); +// member.setPassword(encodedPassword); +// +// // 保存会员 +// this.save(member); +// String destination = rocketmqCustomProperties.getMemberTopic() + ":" + MemberTagsEnum.MEMBER_REGISTER.name(); +// rocketMQTemplate.asyncSend(destination, member, RocketmqSendCallbackBuilder.commonCallback()); +// } +// +// @Override +// public Member editOwn(MemberEditDTO memberEditDTO) { +// // 查询会员信息 +// Member member = this.findByUsername(Objects.requireNonNull(UserContext.getCurrentUser()).getUsername()); +// // 传递修改会员信息 +// BeanUtil.copyProperties(memberEditDTO, member); +// // 修改会员 +// this.updateById(member); +// return member; +// } +// +// @Override +// public Member modifyPass(String oldPassword, String newPassword) { +// AuthUser tokenUser = UserContext.getCurrentUser(); +// if (tokenUser == null) { +// throw new ServiceException(ResultCode.USER_NOT_LOGIN); +// } +// Member member = this.getById(tokenUser.getId()); +// // 判断旧密码输入是否正确 +// if (!new BCryptPasswordEncoder().matches(oldPassword, member.getPassword())) { +// throw new ServiceException(ResultCode.USER_OLD_PASSWORD_ERROR); +// } +// // 修改会员密码 +// LambdaUpdateWrapper lambdaUpdateWrapper = Wrappers.lambdaUpdate(); +// lambdaUpdateWrapper.eq(Member::getId, member.getId()); +// lambdaUpdateWrapper.set(Member::getPassword, new BCryptPasswordEncoder().encode(newPassword)); +// this.update(lambdaUpdateWrapper); +// return member; +// } +// +// @Override +// public Token register(String userName, String password, String mobilePhone, String userSig) { +// // 检测会员信息 +// checkMember(userName, mobilePhone); +// // 创建BCryptPasswordEncoder实例 +// BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); +// +//// 使用passwordEncoder对密码进行加密 +// String encodedPassword = passwordEncoder.encode("123456"); +// // 设置会员信息 +// Member member = new Member(userName, +// encodedPassword, +// mobilePhone); +// member.setUserSig(userSig); // 设置 UserSig +// // 注册成功后用户自动登录 +// registerHandler(member); +// Token token = memberTokenGenerate.createToken(member, false); +// return token; +// } +// +// @Override +// public boolean changeMobile(String mobile) { +// AuthUser tokenUser = Objects.requireNonNull(UserContext.getCurrentUser()); +// Member member = this.findByUsername(tokenUser.getUsername()); +// +// // 判断是否用户登录并且会员ID为当前登录会员ID +// if (!Objects.equals(tokenUser.getId(), member.getId())) { +// throw new ServiceException(ResultCode.USER_NOT_LOGIN); +// } +// // 修改会员手机号 +// LambdaUpdateWrapper lambdaUpdateWrapper = Wrappers.lambdaUpdate(); +// lambdaUpdateWrapper.eq(Member::getId, member.getId()); +// lambdaUpdateWrapper.set(Member::getMobile, mobile); +// return this.update(lambdaUpdateWrapper); +// } +// +// @Override +// public boolean resetByMobile(String uuid, String password) { +// String phone = cache.get(CachePrefix.FIND_MOBILE + uuid).toString(); +// // 根据手机号获取会员判定是否存在此会员 +// if (phone != null) { +// // 修改密码 +// LambdaUpdateWrapper lambdaUpdateWrapper = Wrappers.lambdaUpdate(); +// lambdaUpdateWrapper.eq(Member::getMobile, phone); +// lambdaUpdateWrapper.set(Member::getPassword, new BCryptPasswordEncoder().encode(password)); +// cache.remove(CachePrefix.FIND_MOBILE + uuid); +// return this.update(lambdaUpdateWrapper); +// } else { +// throw new ServiceException(ResultCode.USER_PHONE_NOT_EXIST); +// } +// +// } +// +// @Override +// public Member addMember(MemberAddDTO memberAddDTO) { +// +// // 检测会员信息 +// checkMember(memberAddDTO.getUsername(), memberAddDTO.getMobile()); +// +// // 添加会员 +// Member member = new Member(memberAddDTO.getUsername(), +// StringUtils.isEmpty(memberAddDTO.getPassword()) ? +// new BCryptPasswordEncoder().encode("123456") : // 如果密码为空,使用默认密码123456 +// new BCryptPasswordEncoder().encode(memberAddDTO.getPassword()), +// memberAddDTO.getMobile()); +// registerHandler(member); +// return member; +// } +// +// @Override +// public Member updateMember(ManagerMemberEditDTO managerMemberEditDTO) { +// // 判断是否用户登录并且会员ID为当前登录会员ID +// AuthUser tokenUser = UserContext.getCurrentUser(); +// if (tokenUser == null) { +// throw new ServiceException(ResultCode.USER_NOT_LOGIN); +// } +// // 过滤会员昵称敏感词 +// if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(managerMemberEditDTO.getNickName())) { +// managerMemberEditDTO.setNickName(SensitiveWordsFilter.filter(managerMemberEditDTO.getNickName())); +// } +// // 如果密码不为空则加密密码 +// if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(managerMemberEditDTO.getPassword())) { +// managerMemberEditDTO.setPassword(new BCryptPasswordEncoder().encode(managerMemberEditDTO.getPassword())); +// } +// // 查询会员信息 +// Member member = this.findByUsername(managerMemberEditDTO.getUsername()); +// // 传递修改会员信息 +// BeanUtil.copyProperties(managerMemberEditDTO, member); +// this.updateById(member); +// return member; +// } +// +// @Override +// public IPage getMemberPage(MemberSearchVO memberSearchVO, PageVO page) { +// QueryWrapper queryWrapper = Wrappers.query(); +// // 用户名查询 +// queryWrapper.like(CharSequenceUtil.isNotBlank(memberSearchVO.getUsername()), "m.username", +// memberSearchVO.getUsername()); +// // 用户名查询 +// queryWrapper.like(CharSequenceUtil.isNotBlank(memberSearchVO.getNickName()), "m.nick_name", +// memberSearchVO.getNickName()); +// // 按照电话号码查询 +// queryWrapper.like(CharSequenceUtil.isNotBlank(memberSearchVO.getMobile()), "m.mobile", +// memberSearchVO.getMobile()); +// +// // 根据exper和agent条件查询revenue_sharing +// if (memberSearchVO.getExper() != null && memberSearchVO.getExper() == 1) { +// queryWrapper.eq("rs.id", 3); +// } +// if (memberSearchVO.getAgent() != null && memberSearchVO.getAgent() == 1) { +// queryWrapper.eq("rs.id", 2); +// } +// +// // 时间倒叙排序 +// queryWrapper.orderByDesc("m.create_time"); +// queryWrapper.orderByDesc("ea.created_at"); +// +// IPage memberPage = this.baseMapper.pageByMemberVO(PageUtil.initPage(page), queryWrapper); +// +// // 查询分账比例 +// for (MemberVO memberVO : memberPage.getRecords()) { +// if (memberVO.getAgent() != null && memberVO.getAgent() == 1) { +// // 代理 +// RevenueSharing sharing = revenueSharingMapper.selectByRole("代理"); +// if (sharing != null) memberVO.setPercentage(sharing.getPercentage()); +// } else if (memberVO.getExpert() != null && memberVO.getExpert() == 1) { +// // 达人 +// RevenueSharing sharing = revenueSharingMapper.selectByRole("达人"); +// if (sharing != null) memberVO.setPercentage(sharing.getPercentage()); +// } +// } +// return memberPage; +// } +// @Override +// @PointLogPoint +// @Transactional(rollbackFor = Exception.class) +// public Boolean updateMemberPoint(Long point, String type, String memberId, String content) { +// // 获取当前会员信息 +// Member member = this.getById(memberId); +// if (member != null) { +// // 积分变动后的会员积分 +// long currentPoint; +// // 会员总获得积分 +// long totalPoint = member.getTotalPoint(); +// // 如果增加积分 +// if (type.equals(PointTypeEnum.INCREASE.name())) { +// currentPoint = member.getPoint() + point; +// // 如果是增加积分 需要增加总获得积分 +// totalPoint = totalPoint + point; +// } +// // 否则扣除积分 +// else { +// currentPoint = member.getPoint() - point < 0 ? 0 : member.getPoint() - point; +// } +// member.setPoint(currentPoint); +// member.setTotalPoint(totalPoint); +// boolean result = this.updateById(member); +// if (result) { +// // 发送会员消息 +// MemberPointMessage memberPointMessage = new MemberPointMessage(); +// memberPointMessage.setPoint(point); +// memberPointMessage.setType(type); +// memberPointMessage.setMemberId(memberId); +// String destination = rocketmqCustomProperties.getMemberTopic() + ":" +// + MemberTagsEnum.MEMBER_POINT_CHANGE.name(); +// rocketMQTemplate.asyncSend(destination, memberPointMessage, +// RocketmqSendCallbackBuilder.commonCallback()); +// return true; +// } +// return false; +// +// } +// throw new ServiceException(ResultCode.USER_NOT_EXIST); +// } +// +// /** +// * 更新会员状态 +// * 支持设置封禁时长 +// * +// * @param memberIds 会员ID列表 +// * @param disabled 是否禁用 +// * @param banDays 封禁天数,null表示永久封禁 +// * @return 操作结果代码 +// */ +// @Override +// public ResultCode updateMemberStatus(List memberIds, Boolean disabled, Integer banDays) { +// if (memberIds == null || memberIds.isEmpty()) { +// return ResultCode.USER_NOT_EXIST; +// } +// +// try { +// UpdateWrapper updateWrapper = new UpdateWrapper<>(); +// updateWrapper.in("id", memberIds); +// +// if (Boolean.TRUE.equals(disabled)) { +// // 计算解封时间 +// Date banEndTime = null; +// if (banDays != null && banDays > 0) { +// // 使用 Calendar 设置解封日期 +// Calendar calendar = Calendar.getInstance(); +// calendar.add(Calendar.DAY_OF_MONTH, banDays); +// banEndTime = calendar.getTime(); +// } +// // 设置封禁状态和解封时间 +// updateWrapper.set("delete_flag", true); +// updateWrapper.set("ban_end_time", banEndTime); +// +// // 记录操作日志 +// log.info("封禁会员: memberIds={}, banDays={}, banEndTime={}", +// memberIds, banDays, banEndTime); +// } else { +// // 解除封禁 +// updateWrapper.set("delete_flag", false); +// updateWrapper.set("ban_end_time", null); +// +// // 记录操作日志 +// log.info("解封会员: memberIds={}", memberIds); +// } +// +// boolean result = this.update(updateWrapper); +// +// // 如果更新失败,检查记录是否存在 +// if (!result) { +// long count = this.count(new QueryWrapper().in("id", memberIds)); +// if (count == 0) { +// log.warn("更新会员状态失败: 未找到指定会员, memberIds={}", memberIds); +// return ResultCode.USER_NOT_EXIST; +// } else { +// log.warn("更新会员状态失败: 更新操作失败, memberIds={}", memberIds); +// return ResultCode.ERROR; +// } +// } +// +// return ResultCode.SUCCESS; +// } catch (Exception e) { +// log.error("更新会员状态异常", e); +// return ResultCode.ERROR; +// } +// } +// +// /** +// * 定时任务:检查并解除到期的封禁账号 +// * 每天凌晨执行 +// */ +// @Scheduled(cron = "0 0 0 * * ?") +// public void checkAndUnbanMembers() { +// log.info("开始执行会员自动解封任务"); +// Date now = new Date(); +// +// // 查找到期需要解封的会员数量 +// QueryWrapper countWrapper = new QueryWrapper<>(); +// countWrapper.eq("disabled", true) +// .isNotNull("ban_end_time") +// .le("ban_end_time", now); +// long count = this.count(countWrapper); +// +// if (count > 0) { +// // 解除封禁 +// UpdateWrapper updateWrapper = new UpdateWrapper<>(); +// updateWrapper.set("disabled", false) +// .set("ban_end_time", null) +// .eq("disabled", true) +// .isNotNull("ban_end_time") +// .le("ban_end_time", now); +// +// boolean result = this.update(updateWrapper); +// log.info("会员自动解封任务完成,解封会员数量:{},处理结果:{}", count, result); +// } else { +// log.info("会员自动解封任务完成,无需要解封的会员"); +// } +// } +// +// /** +// * 根据手机号获取会员 +// * +// * @param mobilePhone 手机号 +// * @return 会员 +// */ +// private Long findMember(String mobilePhone, String userName) { +// QueryWrapper queryWrapper = new QueryWrapper<>(); +// queryWrapper.eq("mobile", mobilePhone).or().eq("username", userName); +// return this.baseMapper.selectCount(queryWrapper); +// } +// +// /** +// * 获取cookie中的联合登录对象 +// * +// * @param uuid uuid +// * @param type 状态 +// * @return cookie中的联合登录对象 +// */ +// private ConnectAuthUser getConnectAuthUser(String uuid, String type) { +// Object context = cache.get(ConnectService.cacheKey(type, uuid)); +// if (context != null) { +// return (ConnectAuthUser) context; +// } +// return null; +// } +// +// /** +// * 成功登录,则检测cookie中的信息,进行会员绑定 +// * +// * @param member 会员 +// */ +// private Token loginBindUser(Member member) { +// // 检查该账号是否已有token +// // 先获取所有token对象 +// Object[] keyObjects = cache.keys("{ACCESS_TOKEN}_*").toArray(); +// log.info("Looking for token objects"); +// log.info("Found keys: {}", String.join(", ", Arrays.stream(keyObjects).map(Object::toString).collect(Collectors.toList()))); +// +// String accessToken = null; +// for (Object keyObj : keyObjects) { +// String key = keyObj.toString(); +// String tokenObject = cache.getString(key); +// if (tokenObject != null) { +// try { +// Token token = new Gson().fromJson(tokenObject, Token.class); +// if (token != null && member.getUsername().equals(token.getUsername())) { +// accessToken = token.getAccessToken(); +// log.info("Found access token: {}", accessToken); +// break; +// } +// } catch (Exception e) { +// log.error("Error parsing token object: {}", tokenObject, e); +// } +// } +// } +// +// if (accessToken != null) { +// try { +// // 直接清理token相关的缓存 +// cache.remove(CachePrefix.ACCESS_TOKEN.getPrefix() + member.getUsername()); +// cache.remove(CachePrefix.ACCESS_TOKEN.getPrefix(UserEnums.MEMBER) + accessToken); +// cache.remove(CachePrefix.ACCESS_TOKEN.getPrefix() + accessToken); +// +// // 清理refresh token +// String refreshToken = cache.getString(CachePrefix.REFRESH_TOKEN.getPrefix(UserEnums.MEMBER) + accessToken); +// if (refreshToken != null) { +// cache.remove(CachePrefix.REFRESH_TOKEN.getPrefix(UserEnums.MEMBER) + refreshToken); +// } +// +// log.info("用户[{}]登录系统,清理旧token缓存成功", member.getUsername()); +// } catch (Exception e) { +// log.error("清理用户[{}]token缓存时出错", member.getUsername(), e); +// } +// } +// +// // 获取cookie存储的信息 +// String uuid = CookieUtil.getCookie(ConnectService.CONNECT_COOKIE, ThreadContextHolder.getHttpRequest()); +// String connectType = CookieUtil.getCookie(ConnectService.CONNECT_TYPE, ThreadContextHolder.getHttpRequest()); +// // 如果联合登陆存储了信息 +// if (CharSequenceUtil.isNotEmpty(uuid) && CharSequenceUtil.isNotEmpty(connectType)) { +// try { +// // 获取信息 +// ConnectAuthUser connectAuthUser = getConnectAuthUser(uuid, connectType); +// if (connectAuthUser == null) { +// return null; +// } +// Connect connect = connectService.queryConnect( +// ConnectQueryDTO.builder().unionId(connectAuthUser.getUuid()).unionType(connectType).build()); +// if (connect == null) { +// connect = new Connect(member.getId(), connectAuthUser.getUuid(), connectType); +// connectService.save(connect); +// } +// } catch (ServiceException e) { +// throw e; +// } catch (Exception e) { +// log.error("绑定第三方联合登陆失败:", e); +// } finally { +// // 联合登陆成功与否,都清除掉cookie中的信息 +// CookieUtil.delCookie(ConnectService.CONNECT_COOKIE, ThreadContextHolder.getHttpResponse()); +// CookieUtil.delCookie(ConnectService.CONNECT_TYPE, ThreadContextHolder.getHttpResponse()); +// } +// } +// return null; +// } +// +// /** +// * 检测是否可以绑定第三方联合登陆 返回null原因 包含原因1:redis中已经没有联合登陆信息 2:已绑定其他账号 +// * +// * @return 返回对象则代表可以进行绑定第三方会员,返回null则表示联合登陆无法继续 +// */ +// private ConnectAuthUser checkConnectUser() { +// // 获取cookie存储的信息 +// String uuid = CookieUtil.getCookie(ConnectService.CONNECT_COOKIE, ThreadContextHolder.getHttpRequest()); +// String connectType = CookieUtil.getCookie(ConnectService.CONNECT_TYPE, ThreadContextHolder.getHttpRequest()); +// +// // 如果联合登陆存储了信息 +// if (CharSequenceUtil.isNotEmpty(uuid) && CharSequenceUtil.isNotEmpty(connectType)) { +// // 枚举 联合登陆类型获取 +// ConnectAuthEnum authInterface = ConnectAuthEnum.valueOf(connectType); +// +// ConnectAuthUser connectAuthUser = getConnectAuthUser(uuid, connectType); +// if (connectAuthUser == null) { +// throw new ServiceException(ResultCode.USER_OVERDUE_CONNECT_ERROR); +// } +// // 检测是否已经绑定过用户 +// Connect connect = connectService.queryConnect( +// ConnectQueryDTO.builder().unionType(connectType).unionId(connectAuthUser.getUuid()).build()); +// // 没有关联则返回true,表示可以继续绑定 +// if (connect == null) { +// connectAuthUser.setConnectEnum(authInterface); +// return connectAuthUser; +// } else { +// throw new ServiceException(ResultCode.USER_CONNECT_BANDING_ERROR); +// } +// } else { +// throw new ServiceException(ResultCode.USER_CONNECT_NOT_EXIST_ERROR); +// } +// } +// +// @Override +// public long getMemberNum(MemberSearchVO memberSearchVO) { +// QueryWrapper queryWrapper = Wrappers.query(); +// // 用户名查询 +// queryWrapper.like(CharSequenceUtil.isNotBlank(memberSearchVO.getUsername()), "username", +// memberSearchVO.getUsername()); +// // 按照电话号码查询 +// queryWrapper.like(CharSequenceUtil.isNotBlank(memberSearchVO.getMobile()), "mobile", +// memberSearchVO.getMobile()); +// // 按照状态查询 +// queryWrapper.eq(CharSequenceUtil.isNotBlank(memberSearchVO.getDisabled()), "disabled", +// memberSearchVO.getDisabled().equals(SwitchEnum.OPEN.name()) ? 1 : 0); +// queryWrapper.orderByDesc("create_time"); +// return this.count(queryWrapper); +// } +// +// /** +// * 获取指定会员数据 +// * +// * @param columns 指定获取的列 +// * @param memberIds 会员ids +// * @return 指定会员数据 +// */ +// @Override +// public List> listFieldsByMemberIds(String columns, List memberIds) { +// return this.listMaps(new QueryWrapper().select(columns).in(memberIds != null && !memberIds.isEmpty(), +// "id", memberIds)); +// } +// +// /** +// * 登出 +// */ +// @Override +// public void logout(UserEnums userEnums) { +// String currentUserToken = UserContext.getCurrentUserToken(); +// if (CharSequenceUtil.isNotEmpty(currentUserToken)) { +// AuthUser authUser = UserContext.getCurrentUser(); +// if (authUser != null) { +// try { +// // 清除用户名对应的token缓存,确保单一登录设备失效 +// cache.remove(CachePrefix.ACCESS_TOKEN.getPrefix() + authUser.getUsername()); +// +// // 清除token关联的其他缓存 +// cache.remove(CachePrefix.ACCESS_TOKEN.getPrefix(userEnums) + currentUserToken); +// cache.remove(CachePrefix.ACCESS_TOKEN.getPrefix() + currentUserToken); +// +// log.info("用户[{}]登出系统,清理token缓存成功", authUser.getUsername()); +// } catch (Exception e) { +// log.error("清理用户[{}]token缓存时出错", authUser.getUsername(), e); +// } +// } else { +// cache.remove(CachePrefix.ACCESS_TOKEN.getPrefix(userEnums) + currentUserToken); +// } +// } +// } +// +//// @Override +//// public void cancellation() { +//// +//// AuthUser tokenUser = UserContext.getCurrentUser(); +//// if (tokenUser == null) { +//// throw new ServiceException(ResultCode.USER_NOT_LOGIN); +//// } +//// Member member = this.getById(tokenUser.getId()); +//// //删除联合登录 +//// connectService.deleteByMemberId(member.getId()); +//// //混淆用户信息 +//// this.confusionMember(member); +//// } +//// +//// +//// /** +//// * 混淆之前的会员信息 +//// * +//// * @param member +//// */ +//// private void confusionMember(Member member) { +//// member.setUsername(UuidUtils.getUUID()); +//// member.setMobile(UuidUtils.getUUID() + member.getMobile()); +//// member.setNickName("用户已注销"); +//// member.setDisabled(false); +//// this.updateById(member); +//// } +// /** +// * 获取所有会员的手机号 +// * +// * @return 所有会员的手机号 +// */ +// @Override +// public List getAllMemberMobile() { +// return this.baseMapper.getAllMemberMobile(); +// } +// +// /** +// * 更新会员登录时间为最新时间 +// * +// * @param memberId 会员id +// * @return 是否更新成功 +// */ +// @Override +// public boolean updateMemberLoginTime(String memberId) { +// LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); +// updateWrapper.eq(Member::getId, memberId); +// updateWrapper.set(Member::getLastLoginDate, new Date()); +// return this.update(updateWrapper); +// } +// +// @Override +// public MemberVO getMember(String id) { +// return new MemberVO(this.getById(id)); +// } +// +// /** +// * 检测会员 +// * +// * @param userName 会员名称 +// * @param mobilePhone 手机号 +// */ +// private void checkMember(String userName, String mobilePhone) { +// // 判断手机号是否存在 +// if (findMember(userName, mobilePhone) > 0) { +// throw new ServiceException(ResultCode.USER_EXIST); +// } +// } +// +// @Override +// public Token registerNew(String userName, String password, String mobilePhone, String userSig) { +// // 检测会员信息 +// checkMember(userName, mobilePhone); +// // 设置会员信息 +// Member member = new Member(userName, +// StringUtils.isEmpty(password) ? new BCryptPasswordEncoder().encode("123456") : new BCryptPasswordEncoder().encode(password), +// mobilePhone); +// member.setUserSig(userSig); // 设置 UserSig +// member.setExpert(0); +// // 注册成功后用户自动登录 +// registerHandler(member); +// // 创建商城系统账号,获取短视频系统token +// String tikUser = registerFromShop(mobilePhone, member.getId()); +// if (StringUtils.isNotBlank(tikUser)) { +// Token token = memberTokenGenerate.createToken(member, false); +// token.setTikUser(tikUser); +// return token; +// } +// return null; +// } +// +// @Override +// public Token usernameLoginNew(String username, String password) { +// Member member = this.findMember(username); +// // 判断用户是否存在 +// if (member == null || !member.getDisabled()) { +// throw new ServiceException(ResultCode.USER_NOT_EXIST); +// } +// // 判断密码是否输入正确 +// if (!new BCryptPasswordEncoder().matches(password, member.getPassword())) { +// throw new ServiceException(ResultCode.USER_PASSWORD_ERROR); +// } +// loginBindUser(member); +// // 获取短视频系统账户信息 +// String tikUser = getUserFromShop(member.getId()); +// if (StringUtils.isNotBlank(tikUser)) { +// Token token = memberTokenGenerate.createToken(member, false); +// token.setTikUser(tikUser); +// return token; +// } +// return null; +// } +// +// @Override +// @SystemLogPoint(description = "会员登录", customerLog = "'会员登录请求:'+#mobilePhone") +// public Token mobilePhoneLoginNew(String mobilePhone) throws JSONException { +// try { +// log.info("手机号登录开始: {}", mobilePhone); +// +// // 1. 查询会员 +// QueryWrapper queryWrapper = new QueryWrapper<>(); +// queryWrapper.eq("mobile", mobilePhone); +// Member member = this.baseMapper.selectOne(queryWrapper); +// +// // 2. 处理会员不存在的情况 +// if (member == null) { +// log.info("用户不存在,开始注册流程: {}", mobilePhone); +// member = registerNewMember(mobilePhone); +// // 记录注册日志 +// log.info("新用户注册成功: {}, 用户ID: {}", mobilePhone, member.getId()); +// } else { +// // 记录登录日志 +// log.info("用户登录成功: {}, 用户ID: {}", mobilePhone, member.getId()); +// } +// +// // 3. 检查会员状态 +//// if (!member.getDisabled()) { +//// log.warn("用户已被禁用: {}", mobilePhone); +//// throw new ServiceException(ResultCode.ERROR); +//// } +// +// // 4. 生成或获取 UserSig +// String userSig = member.getUserSig(); +// if (StringUtils.isEmpty(userSig)) { +// userSig = generateUserSig(mobilePhone); +// // 更新会员的 UserSig +// UpdateWrapper updateWrapper = new UpdateWrapper<>(); +// updateWrapper.eq("mobile", mobilePhone); +// updateWrapper.set("user_sig", userSig); +// this.update(updateWrapper); +// member.setUserSig(userSig); +// log.info("更新用户UserSig: {}", mobilePhone); +// } +// +// // 5. 获取短视频系统token +// String tikUser = null; +// try { +// tikUser = getUserFromShop(member.getId()); +// if (StringUtils.isEmpty(tikUser)) { +// log.info("尝试注册商城账号: {}", mobilePhone); +// tikUser = registerFromShop(mobilePhone, member.getId()); +// log.info("商城账号注册成功: {}", mobilePhone); +// } +// } catch (Exception e) { +// log.error("获取短视频系统token失败", e); +// // 这里不抛出异常,允许登录继续 +// } +// +// // 6. 生成登录token +// loginBindUser(member); +// Token token = memberTokenGenerate.createToken(member, false); +// if (StringUtils.isNotBlank(tikUser)) { +// token.setTikUser(tikUser); +// } +// +// log.info("登录流程完成: {}", mobilePhone); +// return token; +// +// } catch (ServiceException e) { +// log.error("登录失败: {}, 错误: {}", mobilePhone, e.getMessage()); +// throw e; +// } catch (Exception e) { +// log.error("登录异常: {}", mobilePhone, e); +// throw new ServiceException(ResultCode.ERROR); +// } +// } +// +// /** +// * 手机号注册新会员 +// */ +// private Member registerNewMember(String mobilePhone) { +// try { +// // 1. 生成 UserSig +// String userSig = generateUserSig(mobilePhone); +// +// // 2. 创建腾讯云IM账号 +// boolean imAccountCreated = createTencentIMAccount(mobilePhone, userSig); +// if (!imAccountCreated) { +// log.error("创建IM账号失败,手机号: {}", mobilePhone); +// throw new ServiceException(ResultCode.ERROR, "创建IM账号失败"); +// } +// +// // 3. 创建会员账号 - 使用默认密码123456 +// Member member = new Member(mobilePhone, UuidUtils.getUUID(), mobilePhone); +// member.setUserSig(userSig); +// member.setDisabled(true); // 设置账号可用 +// +// // 强制设置默认密码123456 +// BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); +// member.setPassword(passwordEncoder.encode("123456")); +// +// registerHandler(member); +// +// log.info("新会员注册成功: {}, 默认密码: 123456", mobilePhone); +// return member; +// } catch (ServiceException e) { +// log.error("注册新会员失败: {}, 错误: {}", mobilePhone, e.getMessage()); +// throw e; +// } catch (Exception e) { +// log.error("注册新会员异常: {}", mobilePhone, e); +// throw new ServiceException(ResultCode.ERROR, "注册失败,请稍后重试"); +// } +// } +// +// /** +// * 生成UserSig +// */ +// private String generateUserSig(String userId) { +// TLSSigAPIv2 tlsSigAPIv2 = new TLSSigAPIv2(SDKAPPID, SECRETKEY); +// long expire = TimeUnit.DAYS.toSeconds(365 * 50); // 50年有效期 +// return tlsSigAPIv2.genUserSig(userId, expire); +// } +// +// /** +// * 创建腾讯云IM账号 +// */ +// private boolean createTencentIMAccount(String userId, String userSig) { +// try { +// String random = String.valueOf(System.currentTimeMillis()); +// +// // 构建请求体 +// JSONObject requestBody = new JSONObject(); +// requestBody.put("UserID", userId); +// requestBody.put("Nick", userId); +// requestBody.put("FaceUrl", "http://www.qq.com"); +// +// // 构建URL - 使用管理员账号(administrator)而不是用户ID来生成签名 +// String urlString = String.format( +// "https://console.tim.qq.com/v4/im_open_login_svc/account_import" + +// "?sdkappid=%s&identifier=%s&usersig=%s&random=%s&contenttype=json", +// SDKAPPID, +// "administrator", // 使用管理员账号 +// generateAdminUserSig(), // 使用管理员的UserSig +// random); +// +// // 创建HTTP客户端 +// OkHttpClient client = new OkHttpClient.Builder() +// .connectTimeout(10, TimeUnit.SECONDS) +// .writeTimeout(10, TimeUnit.SECONDS) +// .readTimeout(10, TimeUnit.SECONDS) +// .build(); +// +// // 发送请求 +// Request request = new Request.Builder() +// .url(urlString) +// .post(RequestBody.create(MediaType.get("application/json; charset=utf-8"), +// requestBody.toString())) +// .build(); +// +// try (Response response = client.newCall(request).execute()) { +// if (!response.isSuccessful()) { +// log.error("创建IM账号失败: {}, 状态码: {}", userId, response.code()); +// return false; +// } +// +// String responseBody = response.body().string(); +// JSONObject jsonResponse = new JSONObject(responseBody); +// int errorCode = jsonResponse.getInt("ErrorCode"); +// +// if (errorCode == 0) { +// log.info("创建IM账号成功: {}", userId); +// return true; +// } else { +// log.error("创建IM账号失败: {}, 错误码: {}, 错误信息: {}", +// userId, errorCode, jsonResponse.optString("ErrorInfo")); +// return false; +// } +// } +// } catch (Exception e) { +// log.error("创建IM账号异常: {}", userId, e); +// return false; +// } +// } +// +// /** +// * 生成管理员UserSig +// */ +// private String generateAdminUserSig() { +// TLSSigAPIv2 tlsSigAPIv2 = new TLSSigAPIv2(SDKAPPID, SECRETKEY); +// long expire = TimeUnit.DAYS.toSeconds(180); // 180天有效期 +// return tlsSigAPIv2.genUserSig("administrator", expire); +// } +// +// @Override +// @Transactional(rollbackFor = Exception.class) +// public void endsetMemberAsAgent(String memberId, String region) { +// // 获取会员信息 +// Member member = this.getById(memberId); +// if (member == null) { +// throw new ServiceException(ResultCode.USER_NOT_EXIST); +// } +// +// // 设置为非代理人 +// member.setAgent(0); +// // 当 region 为 null 时,清除区域信息 +// member.setRegion(region); +// +// // 更新会员信息 +// if (!this.updateById(member)) { +// throw new ServiceException(ResultCode.ERROR); +// } +// } +// @Override +// @Transactional(rollbackFor = Exception.class) +// public void setMemberAsAgent(String memberId, String region) { +// // 获取会员信息 +// Member member = this.getById(memberId); +// if (member == null) { +// throw new ServiceException(ResultCode.USER_NOT_EXIST); +// } +// +// // 检查是否为达人 +// if (member.getExpert() != null && member.getExpert() == 1) { +// throw new ServiceException(ResultCode.EXPERT_EXIST); +// } +// +// // 检查该区域是否已有代理人 +// Integer count = Math.toIntExact(this.count(new LambdaQueryWrapper() +// .eq(Member::getRegion, region) +// .eq(Member::getAgent, 1))); +// if (count > 0) { +// throw new ServiceException(ResultCode.REGION_ALREADY_HAS_AGENT); +// } +// +// // 设置为代理人 +// member.setAgent(1); +// member.setRegion(region); +// +// // 更新会员信息 +// if (!this.updateById(member)) { +// throw new ServiceException(ResultCode.ERROR); +// } +// } +// +// @Override +// @Transactional(rollbackFor = Exception.class) +// public Member updateMemberS(Member member) { +// try { +// // 1. 参数校验 +// if (member == null || StringUtils.isEmpty(member.getId())) { +// throw new ServiceException(ResultCode.PARAMS_ERROR); +// } +// +// // 2. 获取原会员信息 +// Member oldMember = this.getById(member.getId()); +// if (oldMember == null) { +// throw new ServiceException(ResultCode.USER_NOT_EXIST); +// } +// +// // 3. 更新会员信息 +// LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); +// updateWrapper.eq(Member::getId, member.getId()); +// +// // 只更新非空字段 +// +// updateWrapper.set(Member::getNickName, member.getNickName()); +// +// +// updateWrapper.set(Member::getUsername, member.getUsername()); +// +// +// updateWrapper.set(Member::getSex, member.getSex()); +// +// +// updateWrapper.set(Member::getBirthday, member.getBirthday()); +// +// +// updateWrapper.set(Member::getFace, member.getFace()); +// +// +// updateWrapper.set(Member::getRegionId, member.getRegionId()); +// +// updateWrapper.set(Member::getRegion, member.getRegion()); +// +// +// // 4. 执行更新 +// boolean updated = this.update(updateWrapper); +// if (!updated) { +// throw new ServiceException(ResultCode.ERROR); +// } +// +// // 5. 返回更新后的会员信息 +// return this.getById(member.getId()); +// } catch (ServiceException e) { +// log.error("更新会员信息失败: {}", e.getMessage()); +// throw e; +// } catch (Exception e) { +// log.error("更新会员信息异常", e); +// throw new ServiceException(ResultCode.ERROR); +// } +// } +// +// /** +// * 设置默认密码(123456) +// * +// * @param member 会员对象 +// */ +// private void setDefaultPassword(Member member) { +// // 使用BCrypt加密默认密码123456 +// String encodedPassword = new BCryptPasswordEncoder().encode("123456"); +// member.setPassword(encodedPassword); +// } +// +// /** +// * 验证密码格式是否正确 +// * +// * @param password 密码 +// * @return 是否符合BCrypt格式 +// */ +// private boolean isValidBCryptPassword(String password) { +// return password != null && password.startsWith("$2a$") || password.startsWith("$2b$") || password.startsWith("$2y$"); +// } +// +// @Override +// public void updateRevenueSharingPercentage(String id, String percentage) { +// if (id == null || percentage == null) { +// throw new ServiceException("参数不能为空"); +// } +// int updated = revenueSharingMapper.updatePercentageById(id, percentage); +// if (updated == 0) { +// throw new ServiceException("更新失败,未找到对应分账角色"); +// } +// } +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/impl/VerificationServiceImpl.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/impl/VerificationServiceImpl.java new file mode 100644 index 000000000..72142ef46 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/impl/VerificationServiceImpl.java @@ -0,0 +1,228 @@ +package com.wzj.soopin.auth.service.impl; + + +import com.wzj.soopin.auth.domain.dto.VerificationDTO; +import com.wzj.soopin.auth.domain.dto.VerificationSource; +import com.wzj.soopin.auth.domain.dto.entity.enums.VerificationEnums; +import com.wzj.soopin.auth.service.IVerificationService; +import com.wzj.soopin.auth.service.IVerificationSourceService; +import com.wzj.soopin.auth.vo.SerializableStream; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.constant.CachePrefix; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.redis.redis.RedisCache; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.io.InputStream; +import java.net.URL; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +/** + * 认证处理类 + * + * @author Chopper + * @version v1.0 + * 2020-11-17 14:59 + */ +@Slf4j +@Component +public class VerificationServiceImpl { + + @Autowired + private IVerificationSourceService verificationSourceService; + +// +// @Autowired +// private VerificationCodeProperties verificationCodeProperties; +// +// +// @Autowired +// private RedisCache cache; +// +// /** +// * 创建校验 +// * +// * @return 验证码参数 +// */ +// @Override +// public Map createVerification(VerificationEnums verificationEnums, String uuid) { +//// if (uuid == null) { +//// throw new ServiceException(ResultCode.ILLEGAL_REQUEST_ERROR); +//// } +// +// // 添加日志 +// log.info("开始生成验证码 - uuid: {}, type: {}", uuid, verificationEnums); +// +// // 清除可能存在的旧的验证信息 +// String oldKey = cacheKey(verificationEnums, uuid); +// String oldResult = cacheResult(verificationEnums, uuid); +// cache.deleteObject(oldKey); +// cache.deleteObject(oldResult); +// log.info("已清除旧验证码 - oldKey: {}, oldResult: {}", oldKey, oldResult); +// +// //获取验证码配置 +// VerificationDTO verificationDTO = verificationSourceService.getVerificationCache(); +// log.info("获取到验证码配置 - resources: {}, sliders: {}", +// verificationDTO.getVerificationResources().size(), +// verificationDTO.getVerificationSlider().size()); +// +// List verificationResources = verificationDTO.getVerificationResources(); +// List verificationSlider = verificationDTO.getVerificationSlider(); +// +// Random random = new Random(); +// //随机选择需要切的图下标 +// int resourceNum = random.nextInt(verificationResources.size()); +// //随机选择剪切模版下标 +// int sliderNum = random.nextInt(verificationSlider.size()); +// +// //随机选择需要切的图片地址 +// String originalResource = verificationResources.get(resourceNum).getResource(); +// //随机选择剪切模版图片地址 +// String sliderResource = verificationSlider.get(sliderNum).getResource(); +// // 干扰块 +// String interfereResource = verificationSlider.get(sliderNum == verificationSlider.size() - 1 ? +// sliderNum - 1 : sliderNum + 1).getResource(); +// +// try { +// //获取缓存中的资源 +// SerializableStream originalFile = getInputStream(originalResource); +// SerializableStream sliderFile = getInputStream(sliderResource); +// SerializableStream interfereSliderFile = verificationCodeProperties.getInterfereNum() > 0 ? getInputStream(interfereResource) : null; +// //生成数据 +// Map resultMap = SliderImageUtil.pictureTemplatesCut( +// sliderFile, interfereSliderFile, originalFile, +// verificationCodeProperties.getWatermark(), verificationCodeProperties.getInterfereNum()); +// +// // 延长缓存时间到5分钟 +// int effectiveTime = (int) Math.max(verificationCodeProperties.getEffectiveTime(), 1000); +// +// //生成验证参数 +// String cacheKeyStr = cacheKey(verificationEnums, uuid); +// Object randomX = resultMap.get("randomX"); +// cache.setCacheObject(cacheKeyStr, randomX, effectiveTime, TimeUnit.MILLISECONDS); +// +// // 添加详细日志 +// log.info("验证码生成成功 - Key: {}, RandomX: {}, EffectiveTime: {}, ConfigTime: {}", +// cacheKeyStr, randomX, effectiveTime, verificationCodeProperties.getEffectiveTime()); +// +// // 验证缓存是否写入成功 +// Object cachedValue = cache.getCacheObject(cacheKeyStr); +// log.info("缓存写入验证 - Key: {}, CachedValue: {}", cacheKeyStr, cachedValue); +// +// resultMap.put("key", cacheKeyStr); +// resultMap.put("effectiveTime", effectiveTime); +// resultMap.remove("randomX"); +// return resultMap; +// } catch (ServiceException e) { +// log.error("验证码生成服务异常 - \"uuid\": {}, type: {}", uuid, verificationEnums, e); +// throw e; +// } catch (Exception e) { +// log.error("验证码生成异常 - uuid: {}, type: {}", uuid, verificationEnums, e); +// throw new ServiceException(ResultCode.ERROR); +// } +// } +// +// /** +// * 根据网络地址,获取源文件 +// * 这里简单说一下,这里是将不可序列化的inputstream序列化对象,存入redis缓存 +// * +// * @param originalResource +// * @return +// */ +// private SerializableStream getInputStream(String originalResource) throws Exception { +// +// Object object = cache.get(CachePrefix.VERIFICATION_IMAGE.getPrefix() + originalResource); +// if (object != null) { +// return (SerializableStream) object; +// } +// if (StringUtils.isNotEmpty(originalResource)) { +// URL url = new URL(originalResource); +// InputStream inputStream = url.openStream(); +// SerializableStream serializableStream = new SerializableStream(inputStream); +// cache.put(CachePrefix.VERIFICATION_IMAGE.getPrefix() + originalResource, serializableStream); +// return serializableStream; +// } +// return null; +// } +// +// /** +// * 预校验图片 用于前端回显 +// * +// * @param xPos X轴移动距离 +// * @param verificationEnums 验证key +// * @return 验证是否成功 +// */ +// @Override +// public boolean preCheck(Integer xPos, String uuid, VerificationEnums verificationEnums) { +// String key = cacheKey(verificationEnums, uuid); +// Integer randomX = (Integer) cache.get(key); +// +// // 添加调试日志 +// log.debug("验证码预校验 - Key: {}, ExpectedPos: {}, ActualPos: {}", key, randomX, xPos); +// +// if (randomX == null) { +// log.warn("验证码已过期或不存在 - Key: {}", key); +// throw new ServiceException(ResultCode.VERIFICATION_CODE_INVALID); +// } +// +// //验证结果正确 && 删除标记成功 +// if (Math.abs(randomX - xPos) < verificationCodeProperties.getFaultTolerant()) { +// String resultKey = cacheResult(verificationEnums, uuid); +// // 设置验证结果的有效期为60秒 +// cache.put(resultKey, true, 6000L); +// cache.remove(key); +// log.debug("验证码校验成功 - Key: {}, ResultKey: {}", key, resultKey); +// return true; +// } +// createVerification(verificationEnums, uuid); +// log.debug("验证码校验失败 - Key: {}, 误差: {}", key, Math.abs(randomX - xPos)); +// throw new ServiceException(ResultCode.VERIFICATION_ERROR); +// } +// +// /** +// * 验证码校验 +// * +// * @param uuid 用户标识 +// * @param verificationEnums 验证key +// * @return 验证是否成功 +// */ +// @Override +// public boolean check(String uuid, VerificationEnums verificationEnums) { +// String resultKey = cacheResult(verificationEnums, uuid); +// Boolean result = (Boolean) cache.get(resultKey); +// +// // 添加调试日志 +// log.debug("验证结果检查 - Key: {}, Result: {}", resultKey, result); +// +// if (Boolean.TRUE.equals(result)) { +// // 验证通过后,立即删除验证结果,防止重复使用 +// cache.remove(resultKey); +// return true; +// } +// +// // 如果验证结果不存在或已过期,抛出异常 +// log.warn("验证码已失效 - Key: {}", resultKey); +// throw new ServiceException(ResultCode.VERIFICATION_CODE_INVALID); +// } + + /** + * 生成缓存key 记录缓存需要验证的内容 + */ + public static String cacheKey(VerificationEnums verificationEnums, String uuid) { + return CachePrefix.VERIFICATION_KEY.getPrefix() + verificationEnums.name() + "_" + "wzj666"; + } + + /** + * 生成缓存key 记录缓存验证的结果 + */ + public static String cacheResult(VerificationEnums verificationEnums, String uuid) { + return CachePrefix.VERIFICATION_RESULT.getPrefix() + verificationEnums.name() + "_" + "wzj666"; + } + +} + diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/impl/VerificationSourceServiceImpl.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/impl/VerificationSourceServiceImpl.java new file mode 100644 index 000000000..d0e566ee7 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/service/impl/VerificationSourceServiceImpl.java @@ -0,0 +1,56 @@ +package com.wzj.soopin.auth.service.impl; + +import com.wzj.soopin.auth.domain.dto.VerificationDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * 验证码资源维护 业务层实现 + * + * @author Chopper + * @since 2020/11/17 3:48 下午 + */ +@Service +public class VerificationSourceServiceImpl +// extends ServiceImpl implements VerificationSourceService +{ + +// @Autowired +// private Cache cache; +// +// @Override +// public VerificationDTO initCache() { +// List dbList = this.list(); +// List resourceList = new ArrayList<>(); +// List sliderList = new ArrayList<>(); +// for (VerificationSource item : dbList) { +// if (item.getType().equals(VerificationSourceEnum.RESOURCE.name())) { +// resourceList.add(item); +// } else if (item.getType().equals(VerificationSourceEnum.SLIDER.name())) { +// sliderList.add(item); +// } +// } +// VerificationDTO verificationDTO = new VerificationDTO(); +// verificationDTO.setVerificationResources(resourceList); +// verificationDTO.setVerificationSlider(sliderList); +// cache.put(VERIFICATION_CACHE, verificationDTO); +// return verificationDTO; +// } +// +// @Override +// public VerificationDTO getVerificationCache() { +// VerificationDTO verificationDTO; +// try { +// verificationDTO = cache.get(VERIFICATION_CACHE); +// } catch (ClassCastException cce) { +// verificationDTO = null; +// } +// if (verificationDTO == null) { +// return initCache(); +// } +// return verificationDTO; +// } +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/util/Base64DecodeMultipartFile.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/util/Base64DecodeMultipartFile.java new file mode 100644 index 000000000..1a03cb333 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/util/Base64DecodeMultipartFile.java @@ -0,0 +1,127 @@ +package com.wzj.soopin.auth.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; +import java.util.Base64; +import java.util.Base64.Decoder; + +/** + * base64转为multipartFile工具类 + * + * @author Chopper + */ +@Slf4j +public class Base64DecodeMultipartFile implements MultipartFile { + + private final byte[] imgContent; + private final String header; + + public Base64DecodeMultipartFile(byte[] imgContent, String header) { + this.imgContent = imgContent; + this.header = header.split(";")[0]; + } + + @Override + public String getName() { + return System.currentTimeMillis() + Math.random() + "." + header.split("/")[1]; + } + + @Override + public String getOriginalFilename() { + return System.currentTimeMillis() + (int) Math.random() * 10000 + "." + header.split("/")[1]; + } + + @Override + public String getContentType() { + return header.split(":")[1]; + } + + @Override + public boolean isEmpty() { + return imgContent == null || imgContent.length == 0; + } + + @Override + public long getSize() { + return imgContent.length; + } + + @Override + public byte[] getBytes() throws IOException { + return imgContent; + } + + @Override + public InputStream getInputStream() { + return new ByteArrayInputStream(imgContent); + } + + @Override + public void transferTo(File dest) throws IOException, IllegalStateException { + OutputStream stream = null; + try { + stream = new FileOutputStream(dest); + stream.write(imgContent); + } catch (IOException e) { + log.error("transferTo错误", e); + } finally { + assert stream != null; + stream.close(); + } + } + + + public static MultipartFile base64Convert(String base64) { + + String[] baseStrs = base64.split(","); + Decoder decoder = Base64.getDecoder(); + byte[] b = decoder.decode(baseStrs[1]); + + for (int i = 0; i < b.length; ++i) { + if (b[i] < 0) { + b[i] += 256; + } + } + return new Base64DecodeMultipartFile(b, baseStrs[0]); + } + + + public static InputStream base64ToInputStream(String base64) { + ByteArrayInputStream stream = null; + try { + byte[] bytes = Base64.getDecoder().decode(base64); + stream = new ByteArrayInputStream(bytes); + } catch (Exception e) { + log.error("base64ToInputStream错误", e); + } + return stream; + } + + public static String inputStreamToStream(InputStream in) { + byte[] data = null; + //读取图片字节数组 + try { + ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); + byte[] buff = new byte[100]; + int rc = 0; + while ((rc = in.read(buff, 0, 100)) > 0) { + swapStream.write(buff, 0, rc); + } + data = swapStream.toByteArray(); + } catch (IOException e) { + log.error("转码错误", e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + log.error("inputStreamToStream错误", e); + } + } + } + return Base64.getEncoder().encodeToString(data); + } +} + diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/util/SmsUtil.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/util/SmsUtil.java new file mode 100644 index 000000000..654ff1225 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/util/SmsUtil.java @@ -0,0 +1,59 @@ +package com.wzj.soopin.auth.util; + + +import com.wzj.soopin.auth.domain.dto.entity.enums.VerificationEnums; + +import java.util.List; +import java.util.Map; + +/** + * 短信接口 + * + * @author Chopper + * @version v4.0 + * @since 2020/11/30 15:44 + */ +public interface SmsUtil { + + + /** + * 验证码发送 + * + * @param mobile 手机号 + * @param verificationEnums 验证码场景 + * @param uuid 用户标识uuid + */ + void sendSmsCode(String mobile, VerificationEnums verificationEnums, String uuid); + + /** + * 验证码验证 + * + * @param mobile 手机号 + * @param verificationEnums 验证码场景 + * @param uuid 用户标识uuid + * @param code 待验证code + * @return 操作状态 + */ + boolean verifyCode(String mobile, VerificationEnums verificationEnums, String uuid, String code); + + /** + * 短信发送 + * + * @param mobile 接收手机号 + * @param param 参数 + * @param templateCode 模版code + * @param signName 签名名称 + */ + void sendSmsCode(String signName, String mobile, Map param, String templateCode); + + /** + * 短信批量发送 + * + * @param mobile 接收手机号 + * @param signName 签名 + * @param templateCode 模版code + */ + void sendBatchSms(String signName, List mobile, String templateCode); + + +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/util/TLSSigAPIv2.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/util/TLSSigAPIv2.java new file mode 100644 index 000000000..590af2ea5 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/util/TLSSigAPIv2.java @@ -0,0 +1,194 @@ +package com.wzj.soopin.auth.util; + + +import cn.hutool.json.JSONException; +import cn.hutool.json.JSONObject; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Base64; +import java.util.zip.Deflater; + +public class TLSSigAPIv2 { + private static long sdkappid = 1600080789; // 替换为您的 SDKAppID + + private static String key = "311b5309d714a20f7f5b54360ee21b1e24ec208ebcd25ce8f47d24753bccc091"; // 替换为您的密钥 + + public TLSSigAPIv2(long sdkappid, String key) { + this.sdkappid = sdkappid; + this.key = key; + } + + /** + * 生成 UserSig 签名 + * + * @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符 + * @param expire - UserSig 票据的过期时间,单位是秒,比如 86400 代表生成的 UserSig 票据在一天后就无法再使用了 + * @return usersig - 生成的签名 + */ + public String genUserSig(String userid, long expire) { + return genUserSig(userid, expire, null); + } + + /** + * 生成带 UserBuf 的 UserSig + * + * @param userid - 用户id + * @param expire - 过期时间,单位秒 + * @param userbuf - 用户数据 + * @return 生成的签名 + */ + private String genUserSig(String userid, long expire, byte[] userbuf) { + long currTime = System.currentTimeMillis() / 1000; + + JSONObject sigDoc = new JSONObject(); + try { + sigDoc.put("TLS.ver", "2.0"); + sigDoc.put("TLS.identifier", userid); + sigDoc.put("TLS.sdkappid", sdkappid); + sigDoc.put("TLS.expire", expire); + sigDoc.put("TLS.time", currTime); + + String base64UserBuf = null; + if (null != userbuf) { + base64UserBuf = Base64.getEncoder().encodeToString(userbuf).replaceAll("\\s*", ""); + sigDoc.put("TLS.userbuf", base64UserBuf); + } + + String sig = hmacsha256(userid, currTime, expire, base64UserBuf); + if (sig.length() == 0) { + return ""; + } + sigDoc.put("TLS.sig", sig); + + Deflater compressor = new Deflater(); + compressor.setInput(sigDoc.toString().getBytes(StandardCharsets.UTF_8)); + compressor.finish(); + byte[] compressedBytes = new byte[2048]; + int compressedBytesLength = compressor.deflate(compressedBytes); + compressor.end(); + + return Base64.getEncoder().encodeToString( + Arrays.copyOfRange(compressedBytes, 0, compressedBytesLength) + ).replaceAll("\\s*", ""); + + } catch (JSONException e) { + return ""; + } + } + + /** + * 生成 PrivateMapKey + */ + public String genPrivateMapKey(String userid, long expire, long roomid, long privilegeMap) { + byte[] userbuf = genUserBuf(userid, roomid, expire, privilegeMap, 0, ""); + return genUserSig(userid, expire, userbuf); + } + + /** + * 生成带字符串房间号的 PrivateMapKey + */ + public String genPrivateMapKeyWithStringRoomID(String userid, long expire, String roomstr, long privilegeMap) { + byte[] userbuf = genUserBuf(userid, 0, expire, privilegeMap, 0, roomstr); + return genUserSig(userid, expire, userbuf); + } + + /** + * 生成 HMAC-SHA256 签名 + */ + private String hmacsha256(String identifier, long currTime, long expire, String base64Userbuf) { + String contentToBeSigned = "TLS.identifier:" + identifier + "\n" + + "TLS.sdkappid:" + sdkappid + "\n" + + "TLS.time:" + currTime + "\n" + + "TLS.expire:" + expire + "\n"; + if (null != base64Userbuf) { + contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n"; + } + + try { + byte[] byteKey = key.getBytes(StandardCharsets.UTF_8); + Mac hmac = Mac.getInstance("HmacSHA256"); + SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256"); + hmac.init(keySpec); + byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(byteSig).replaceAll("\\s*", ""); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + return ""; + } + } + + /** + * 生成用户数据 + */ + private byte[] genUserBuf(String account, long dwAuthID, long dwExpTime, + long dwPrivilegeMap, long dwAccountType, String roomStr) { + int accountLength = account.length(); + int roomStrLength = roomStr.length(); + int offset = 0; + int bufLength = 1 + 2 + accountLength + 20; + + if (roomStrLength > 0) { + bufLength = bufLength + 2 + roomStrLength; + } + + byte[] userbuf = new byte[bufLength]; + + // 版本号 + userbuf[offset++] = (byte)(roomStrLength > 0 ? 1 : 0); + + // 账号长度 + userbuf[offset++] = (byte) ((accountLength & 0xFF00) >> 8); + userbuf[offset++] = (byte) (accountLength & 0x00FF); + + // 写入账号 + for (; offset < 3 + accountLength; ++offset) { + userbuf[offset] = (byte) account.charAt(offset - 3); + } + + // 写入 sdkappid + userbuf[offset++] = (byte) ((sdkappid & 0xFF000000) >> 24); + userbuf[offset++] = (byte) ((sdkappid & 0x00FF0000) >> 16); + userbuf[offset++] = (byte) ((sdkappid & 0x0000FF00) >> 8); + userbuf[offset++] = (byte) (sdkappid & 0x000000FF); + + // 写入房间号 + userbuf[offset++] = (byte) ((dwAuthID & 0xFF000000) >> 24); + userbuf[offset++] = (byte) ((dwAuthID & 0x00FF0000) >> 16); + userbuf[offset++] = (byte) ((dwAuthID & 0x0000FF00) >> 8); + userbuf[offset++] = (byte) (dwAuthID & 0x000000FF); + + // 过期时间 + long expire = System.currentTimeMillis() / 1000 + dwExpTime; + userbuf[offset++] = (byte) ((expire & 0xFF000000) >> 24); + userbuf[offset++] = (byte) ((expire & 0x00FF0000) >> 16); + userbuf[offset++] = (byte) ((expire & 0x0000FF00) >> 8); + userbuf[offset++] = (byte) (expire & 0x000000FF); + + // 权限位 + userbuf[offset++] = (byte) ((dwPrivilegeMap & 0xFF000000) >> 24); + userbuf[offset++] = (byte) ((dwPrivilegeMap & 0x00FF0000) >> 16); + userbuf[offset++] = (byte) ((dwPrivilegeMap & 0x0000FF00) >> 8); + userbuf[offset++] = (byte) (dwPrivilegeMap & 0x000000FF); + + // 账号类型 + userbuf[offset++] = (byte) ((dwAccountType & 0xFF000000) >> 24); + userbuf[offset++] = (byte) ((dwAccountType & 0x00FF0000) >> 16); + userbuf[offset++] = (byte) ((dwAccountType & 0x0000FF00) >> 8); + userbuf[offset++] = (byte) (dwAccountType & 0x000000FF); + + // 房间号字符串 + if (roomStrLength > 0) { + userbuf[offset++] = (byte) ((roomStrLength & 0xFF00) >> 8); + userbuf[offset++] = (byte) (roomStrLength & 0x00FF); + for (; offset < bufLength; ++offset) { + userbuf[offset] = (byte) roomStr.charAt(offset - (bufLength - roomStrLength)); + } + } + + return userbuf; + } +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/vo/MemberSearchVO.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/vo/MemberSearchVO.java new file mode 100644 index 000000000..2fcb2e366 --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/vo/MemberSearchVO.java @@ -0,0 +1,34 @@ +package com.wzj.soopin.auth.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 会员搜索VO + * + * @author Bulbasaur + * @since 2020/12/15 10:48 + */ +@Data +public class MemberSearchVO { + + @ApiModelProperty(value = "用户名") + private String username; + + @ApiModelProperty(value = "昵称") + private String nickName; + + @ApiModelProperty(value = "手机号") + private String mobile; + + @ApiModelProperty(value = "专家标识") + private Integer exper; + + @ApiModelProperty(value = "代理标识") + private Integer agent; + + /** + */ + @ApiModelProperty(value = "会员状态") + private String disabled; +} diff --git a/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/vo/SerializableStream.java b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/vo/SerializableStream.java new file mode 100644 index 000000000..e97d0483a --- /dev/null +++ b/ruoyi-modules/ruoyi-auth/src/main/java/com/wzj/soopin/auth/vo/SerializableStream.java @@ -0,0 +1,24 @@ +package com.wzj.soopin.auth.vo; + +import com.wzj.soopin.auth.util.Base64DecodeMultipartFile; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.InputStream; + +/** + * 序列化的input stream + * + * @author Chopper + */ +@Data +@NoArgsConstructor +public class SerializableStream { + private String base64; + + public SerializableStream(InputStream inputStream) { + this.base64 = Base64DecodeMultipartFile.inputStreamToStream(inputStream); + } + +} + diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/controller/MemberController.java b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/controller/MemberController.java index de88d5f6b..d27a3a1ef 100644 --- a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/controller/MemberController.java +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/controller/MemberController.java @@ -3,13 +3,12 @@ package com.wzj.soopin.member.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.wzj.soopin.member.convert.MemberConvert; import com.wzj.soopin.member.domain.bo.MemberBO; import com.wzj.soopin.member.domain.form.ChangeMemberStatusForm; import com.wzj.soopin.member.domain.po.Member; import com.wzj.soopin.member.domain.vo.MemberVO; -import com.wzj.soopin.member.service.IMemberService; +import com.wzj.soopin.member.service.IMemberCrudService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.dromara.common.core.domain.R; @@ -19,8 +18,6 @@ import org.dromara.common.log.enums.BusinessType; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.web.core.BaseController; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -35,7 +32,7 @@ import java.util.List; @RestController public class MemberController extends BaseController { @Autowired - private IMemberService service; + private IMemberCrudService service; @Autowired private MemberConvert convert; diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/domain/bo/MemberAddDTO.java b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/domain/bo/MemberAddDTO.java new file mode 100644 index 000000000..37713918a --- /dev/null +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/domain/bo/MemberAddDTO.java @@ -0,0 +1,30 @@ +package com.wzj.soopin.member.domain.bo; + +import io.swagger.annotations.ApiModelProperty; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.Data; + + +/** + * 添加会员DTO + * + * @author Bulbasaur + * @since 2020/12/14 16:31 + */ +@Data +public class MemberAddDTO { + @NotEmpty(message = "会员用户名必填") + @Size(max = 30,message = "会员用户名最长30位") + @ApiModelProperty(value = "会员用户名") + private String username; + + @ApiModelProperty(value = "会员密码") + private String password; + + @NotEmpty(message = "手机号码不能为空") + @ApiModelProperty(value = "手机号码", required = true) + @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误") + private String mobile; +} diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/domain/bo/MemberEditDTO.java b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/domain/bo/MemberEditDTO.java new file mode 100644 index 000000000..8f2e73f97 --- /dev/null +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/domain/bo/MemberEditDTO.java @@ -0,0 +1,51 @@ +package com.wzj.soopin.member.domain.bo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModelProperty; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 会员信息修改DTO + * + * @author Bulbasaur + * @since 2020/12/11 14:39 + */ +@Data +public class MemberEditDTO { + + + @ApiModelProperty(value = "昵称", required = true) + @Size(min = 2, max = 20, message = "会员昵称必须为2到20位之间") + private String nickName; + + @ApiModelProperty(value = "会员地址ID") + private String regionId; + + @ApiModelProperty(value = "会员地址") + private String region; + + @Min(message = "必须为数字且1为男,0为女", value = 0) + @Max(message = "必须为数字且1为男,0为女", value = 1) + @NotNull(message = "会员性别不能为空") + @ApiModelProperty(value = "会员性别,1为男,0为女", required = true) + private Integer sex; + + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @ApiModelProperty(value = "会员生日") + private Date birthday; + + @ApiModelProperty(value = "详细地址") + private String address; + + @ApiModelProperty(value = "会员头像") + private String face; + +} diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/mapper/MemberMapper.java b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/mapper/MemberMapper.java index 3938925f1..3e7d14685 100644 --- a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/mapper/MemberMapper.java +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/mapper/MemberMapper.java @@ -1,7 +1,13 @@ package com.wzj.soopin.member.mapper; +import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Constants; import com.wzj.soopin.member.domain.po.Member; +import com.wzj.soopin.member.domain.vo.MemberVO; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; import java.util.List; @@ -18,4 +24,27 @@ public interface MemberMapper extends BaseMapper { * @return 会员信息集合 */ List selectByEntity(Member member); + + /** + * 获取所有的会员手机号 + * @return 会员手机号 + */ + @Select("select m.mobile from li_member m") + List getAllMemberMobile(); + + @Select("SELECT m.*, ea.created_at AS createdAt FROM li_member m " + + "LEFT JOIN li_expert_apply ea ON m.id = ea.member_id " + + "${ew.customSqlSegment}") + IPage pageByMemberVO(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + + @Select("SELECT COUNT(*) FROM li_member WHERE username = #{username}") + + int countByUsername(@Param("username") String username); + + + @Select("SELECT * \n" + + "FROM li_member \n" + + "WHERE id = #{memberId} \n" + + " AND expert = 1;") + Member isExpert(String memberId); } diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/IMemberService.java b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/IMemberCrudService.java similarity index 82% rename from ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/IMemberService.java rename to ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/IMemberCrudService.java index f3c572605..5f49be0fc 100644 --- a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/IMemberService.java +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/IMemberCrudService.java @@ -4,7 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.wzj.soopin.member.domain.form.ChangeMemberStatusForm; import com.wzj.soopin.member.domain.po.Member; -public interface IMemberService extends IService { +public interface IMemberCrudService extends IService { Integer changeStatus(ChangeMemberStatusForm dto); int updateMark(Member member); diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/MemberServiceImpl.java b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/MemberCrudServiceImpl.java similarity index 82% rename from ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/MemberServiceImpl.java rename to ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/MemberCrudServiceImpl.java index 5ff9f756b..f42ba8d46 100644 --- a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/MemberServiceImpl.java +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/MemberCrudServiceImpl.java @@ -1,18 +1,13 @@ package com.wzj.soopin.member.service.impl; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.wzj.soopin.member.domain.form.ChangeMemberStatusForm; import com.wzj.soopin.member.domain.po.Member; -import com.wzj.soopin.member.domain.bo.MemberBO; import com.wzj.soopin.member.mapper.MemberCartMapper; import com.wzj.soopin.member.mapper.MemberMapper; -import com.wzj.soopin.member.service.IMemberService; -import org.apache.commons.lang3.StringUtils; +import com.wzj.soopin.member.service.IMemberCrudService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.time.LocalDateTime; @@ -24,7 +19,7 @@ import java.time.LocalDateTime; * @author zcc */ @Service -public class MemberServiceImpl extends ServiceImpl implements IMemberService { +public class MemberCrudServiceImpl extends ServiceImpl implements IMemberCrudService { @Autowired private MemberMapper memberMapper;