基于mall4j产品的二开项目后端
lee
2024-12-19 9106a889533d011a34253addb7a719fe800852cf
init
525 files added
38966 ■■■■■ changed files
yami-shop-combo/pom.xml 22 ●●●●● patch | view | raw | blame | history
yami-shop-combo/yami-shop-combo-multishop/pom.xml 27 ●●●●● patch | view | raw | blame | history
yami-shop-combo/yami-shop-combo-multishop/src/main/java/com/yami/shop/combo/multishop/config/SwaggerConfiguration.java 36 ●●●●● patch | view | raw | blame | history
yami-shop-combo/yami-shop-combo-multishop/src/main/java/com/yami/shop/combo/multishop/controller/ComboController.java 92 ●●●●● patch | view | raw | blame | history
yami-shop-combo/yami-shop-combo-multishop/src/main/java/com/yami/shop/combo/multishop/controller/ComboProdController.java 97 ●●●●● patch | view | raw | blame | history
yami-shop-combo/yami-shop-combo-multishop/src/main/java/com/yami/shop/combo/multishop/controller/GiveawayController.java 84 ●●●●● patch | view | raw | blame | history
yami-shop-combo/yami-shop-combo-multishop/src/main/java/com/yami/shop/combo/multishop/controller/GiveawayProdController.java 68 ●●●●● patch | view | raw | blame | history
yami-shop-combo/yami-shop-combo-platform/pom.xml 28 ●●●●● patch | view | raw | blame | history
yami-shop-combo/yami-shop-combo-platform/src/main/java/com/yami/shop/combo/platform/config/SwaggerConfiguration.java 36 ●●●●● patch | view | raw | blame | history
yami-shop-combo/yami-shop-combo-platform/src/main/java/com/yami/shop/combo/platform/task/ComboTask.java 48 ●●●●● patch | view | raw | blame | history
yami-shop-combo/yami-shop-combo-platform/src/main/java/com/yami/shop/combo/platform/task/GiveawayTask.java 49 ●●●●● patch | view | raw | blame | history
yami-shop-common/pom.xml 136 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/annotation/RedisLock.java 47 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/annotation/SysLog.java 24 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/aspect/RedisLockAspect.java 74 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/ALiDaYu.java 26 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/AliOss.java 31 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/Alipay.java 42 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/CDNConfigBean.java 33 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/CDNDevice.java 28 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/CdnIncomeRadioConfig.java 12 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/ContranctInfo.java 78 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/CpsConfig.java 28 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/DateVO.java 24 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/Domain.java 28 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/ExchangeRate.java 52 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/HuaWeiOss.java 31 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/Minio.java 30 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/PayPal.java 44 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/QCloud.java 30 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/Qiniu.java 31 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/Quick100.java 38 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/QuickAli.java 31 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/QuickBird.java 64 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/SensitiveWord.java 36 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/ShopLuckyCoin.java 21 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/SwitchBaseModel.java 25 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/SysConfig.java 37 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/SysPayConfig.java 82 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/SysProdConfig.java 25 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/SysServiceConfig.java 33 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/SysUpgradeInfo.java 61 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/TaskPageUrl.java 13 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/WxApp.java 26 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/WxMiniApp.java 31 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/WxMp.java 30 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/WxPay.java 70 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/bean/event/GetSensitiveWordEvent.java 34 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/BigSellerConfig.java 74 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/Constant.java 317 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/DefaultExceptionHandlerConfig.java 82 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/Ip2RegionConfig.java 51 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/LocalDateTimeSerializerConfig.java 41 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/MyDetaObjectHandler.java 36 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/MybatisPlusConfig.java 67 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/OrikaConfig.java 34 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/RedisCacheConfig.java 134 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/SensitiveWordConfig.java 194 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/ShopBeanConfig.java 29 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/SnowflakeConfig.java 35 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/SwaggerConfig.java 95 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/WebMvcConfig.java 44 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/config/WebhookConstant.java 117 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/constants/CacheNames.java 27 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/constants/DictConstant.java 116 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/constants/EsCacheNames.java 26 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/constants/OauthCacheNames.java 42 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/constants/OrderCacheNames.java 63 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/constants/PCDNConstant.java 26 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/constants/PaypalConstant.java 264 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/constants/ProductCacheNames.java 71 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/constants/ResultMsg.java 49 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/constants/ShopCacheNames.java 18 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/enums/CodeBaseEnum.java 11 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/enums/EsRenovationProductSortEnum.java 68 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/enums/LuckyCoinEnum.java 26 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/enums/PayType.java 105 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/enums/QiniuZone.java 48 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/enums/StatusEnum.java 89 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/enums/UserLevelType.java 44 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/enums/WalletEnum.java 89 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/exception/YamiShopBindException.java 75 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/filter/SensitiveFilter.java 112 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/handler/EnumTypeHandler.java 67 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/handler/HttpHandler.java 88 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/handler/SensitiveHandler.java 259 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/i18n/I18nMessage.java 144 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/i18n/LanguageEnum.java 82 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/i18n/YamiLocaleChangeFilter.java 52 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/i18n/YamiLocaleChangeInterceptor.java 57 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/response/R.java 214 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/response/ResponseCode.java 22 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/response/ResponseEnum.java 174 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/response/ServerResponseEntity.java 214 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/response/WxLiveProdResponse.java 40 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/response/WxServerResponse.java 50 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/serializer/json/ImgJsonSerializer.java 73 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/Arith.java 211 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/BmapPoint.java 58 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/CacheManagerUtil.java 53 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/CharUtil.java 38 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/DateParam.java 26 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/DateUtils.java 444 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/GraphUtils.java 206 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/HandCardUtil.java 42 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/HttpContextUtils.java 79 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/IPHelper.java 46 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/IdCardCheck.java 148 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/IdUtil.java 92 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/ImageUtil.java 98 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/Json.java 182 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/PageAdapter.java 32 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/PageParam.java 167 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/PayUtil.java 33 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/PoiExcelUtil.java 270 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/PrincipalUtil.java 130 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/RedisUtil.java 294 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/SimpleCaptcha.java 87 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/SpelUtil.java 58 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/SpringContextUtils.java 54 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/WordUtil.java 266 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/util/WriteOffCodeUtil.java 58 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wrapper/RequestWrapper.java 102 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wrapper/ResponseWrapper.java 77 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/WxInterfaceUtil.java 334 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/GoodsInfoReqParam.java 44 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/GoodsListReqParam.java 31 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/GoodsReqInfo.java 44 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/ImageUploadReqParam.java 29 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/LiveUserReqInfo.java 29 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/PageLiveRoomInfo.java 28 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/UpdateGoodsInfoReqParam.java 45 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/WxInterfaceInfo.java 46 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/WxLiveRoomInfo.java 114 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/WxRoomProdInfo.java 32 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/GoodsInfoRespParam.java 72 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/GoodsListInfosRespParam.java 52 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/GoodsListRespParam.java 30 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/ImageResponse.java 29 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/LiveUserRespInfo.java 41 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/RoomDetailResponse.java 97 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/RoomResponse.java 27 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/resources/i18n/messages.properties patch | view | raw | blame | history
yami-shop-common/src/main/resources/i18n/messages_en.properties 726 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/resources/i18n/messages_zh.properties 734 ●●●●● patch | view | raw | blame | history
yami-shop-common/src/main/resources/ip2region.xdb patch | view | raw | blame | history
yami-shop-coupon/pom.xml 26 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-api/pom.xml 27 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/config/SwaggerConfiguration.java 38 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/controller/CouponController.java 159 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/controller/MyCouponController.java 129 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/listener/SubmitOrderActivityListener.java 88 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/listener/SubmitOrderListener.java 96 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/manager/impl/CouponConfirmOrderManagerImpl.java 122 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/util/ChooseCouponHelper.java 321 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/pom.xml 21 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/constants/CouponStatusEnum.java 42 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/constants/UserCouponRecordStatus.java 46 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/constants/UserCouponStatus.java 46 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/constants/ValidTimeTypeEnum.java 35 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/dao/CouponMapper.java 223 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/dao/CouponProdMapper.java 41 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/dao/CouponUseRecordMapper.java 80 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/dao/CouponUserMapper.java 195 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/dto/CouponRecordDTO.java 40 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/listener/CancelOrderListener.java 43 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/listener/OrderRefundListener.java 117 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/listener/PaySuccessOrderListener.java 69 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/model/Coupon.java 124 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/model/CouponProd.java 48 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/model/CouponUseRecord.java 74 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/model/CouponUser.java 90 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/param/UserCouponParam.java 21 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/CouponProdService.java 21 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/CouponService.java 234 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/CouponUseRecordService.java 54 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/CouponUserService.java 89 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/impl/CouponProdServiceImpl.java 29 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/impl/CouponServiceImpl.java 582 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/impl/CouponUseRecordServiceImpl.java 120 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/impl/CouponUserServiceImpl.java 178 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/resources/mapper/CouponMapper.xml 522 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/resources/mapper/CouponProdMapper.xml 33 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/resources/mapper/CouponUseRecordMapper.xml 80 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-common/src/main/resources/mapper/CouponUserMapper.xml 246 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-multishop/pom.xml 27 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-multishop/src/main/java/com/yami/shop/coupon/multishop/config/SwaggerConfiguration.java 38 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-multishop/src/main/java/com/yami/shop/coupon/multishop/controller/CouponController.java 206 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-multishop/src/main/java/com/yami/shop/coupon/multishop/controller/CouponProdController.java 75 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-multishop/src/main/java/com/yami/shop/coupon/multishop/controller/CouponUserController.java 75 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-platform/pom.xml 27 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-platform/src/main/java/com/yami/shop/coupon/platform/config/SwaggerConfiguration.java 36 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-platform/src/main/java/com/yami/shop/coupon/platform/controller/CouponController.java 268 ●●●●● patch | view | raw | blame | history
yami-shop-coupon/yami-shop-coupon-platform/src/main/java/com/yami/shop/coupon/platform/task/CouponTask.java 94 ●●●●● patch | view | raw | blame | history
yami-shop-cps/pom.xml 23 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-api/pom.xml 34 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-api/src/main/java/com/yami/shop/cps/api/config/SwaggerConfiguration.java 35 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-api/src/main/java/com/yami/shop/cps/api/controller/PddCpsController.java 102 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-api/src/main/java/com/yami/shop/cps/api/controller/TbCpsController.java 174 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/pom.xml 97 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/client/AbstractDtkApiClient.java 121 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/client/ApiRequest.java 15 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/client/DtkApiClient.java 40 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/client/DtkApiRequest.java 49 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/client/DtkClient.java 21 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/constant/DtkApiConstant.java 48 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/controller/base/BaseController.java 56 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/controller/base/TaoBaoUnionController.java 130 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/exception/DtkApiException.java 28 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/exception/DtkResultEnum.java 38 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/exception/Result.java 23 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/http/Logger.java 217 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/http/StringUtils.java 169 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/http/WebUtils.java 484 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/base/DtkPageParamRequest.java 23 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/base/DtkUrlParamRequest.java 19 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkActivityLinkRequest.java 59 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkCommodityMaterialsRequest.java 53 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkCouponQueryRequest.java 52 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkCreatTaokoulingRequest.java 61 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkCzmfTransformLinkRequest.java 63 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkFirstOrderGiftMoneyRequest.java 59 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkGetCollectionListRequest.java 61 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkGetOrderDetailsRequest.java 75 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkGetOwnerGoodsRequest.java 58 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkGetPrivilegeLinkRequest.java 72 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkGetSuperCategoryRequest.java 50 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkGoodsCommentListRequest.java 59 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkJdBatchTransformLinkRequest.java 61 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkJdCommodityTransformLinkRequest.java 67 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkJdLinkAnalysisRequest.java 52 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkJdOrderQueryRequest.java 69 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkJdOrderQueryV2Request.java 68 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkMergeRedEnvelopesRequest.java 56 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkParseContentRequest.java 53 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkParseTaokoulingRequest.java 53 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkPddTransformLinkRequest.java 59 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkShopConvertRequest.java 57 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkTbCashGiftRequest.java 89 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkTwdToTwdRequest.java 60 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/ShearPlateDistinguishRequest.java 64 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkGoodsDetailsRequest.java 52 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkGoodsListRequest.java 113 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkJdCommodityDetailsRequest.java 53 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkNewestGoodsRequest.java 91 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkPddGoodsDetailsRequest.java 60 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkPullGoodsByTimeRequest.java 68 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkStaleGoodsByTimeRequest.java 54 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkGetDtkSearchGoodsRequest.java 93 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkGetTbServiceRequest.java 86 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkGetTop100Request.java 50 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkHotSearchListRequest.java 50 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkJdGoodsTypeRequest.java 53 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkJdUnionQueryRequest.java 97 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkListSuperGoodsRequest.java 81 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkPddGoodsTypeRequest.java 53 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkPddOrderIncrementSearchRequest.java 79 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkPddUnionQueryRequest.java 85 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkSearchSuggestionRequest.java 56 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkTbkScPunishOrderGetRequest.java 69 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkTbkScRelationRefundRequest.java 73 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkActivityCatalogueRequest.java 49 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkActivityGoodsListRequest.java 60 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkAlbumListRequest.java 56 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkBigBrandDiscountRequest.java 49 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkCarouselMapResponseRequest.java 49 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkCatalogueRequest.java 49 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkDdqGoodsListRequest.java 50 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkExclusiveGoodsListRequest.java 54 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkExplosiveGoodsListRequest.java 56 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkFriendsCircleListRequest.java 62 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetBrandGoodsListRequest.java 55 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetBrandListRequest.java 50 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetColumnListRequest.java 54 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetHalfPriceDayRequest.java 50 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetRankListRequest.java 53 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetRankingListRequest.java 49 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetTbTopicListRequest.java 54 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkHighCommissionSelectedRequest.java 54 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkHistoricalNewLowCommodityRequest.java 56 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkJdCommodityDiscountPriceRequest.java 54 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkJdNewYearCommodityRequest.java 58 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkJdOneDollarPurchaseOrderInquiryRequest.java 62 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkListSimilerGoodsByOpenRequest.java 55 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkLiveMaterialGoodsListRequest.java 53 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkMostPopularCommodityListRequest.java 51 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkNineFreeShippingRequest.java 54 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkOpGoodsListRequest.java 54 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkPopularAnchorCommendRequest.java 50 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkPriceTrendRequest.java 54 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkRealTimeListRequest.java 50 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkSingleAlbumCommodityRequest.java 52 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkSubdivisionCategoryListRequest.java 54 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkSuperDiscountGoodsRequest.java 56 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkTipOffRequest.java 53 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkTopicGoodsListRequest.java 54 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/subranking/DtkGetRankingListBaseRequest.java 25 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/subranking/DtkGetRankingListByHotSearchRequest.java 47 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/subranking/DtkGetRankingListByHotWordRequest.java 47 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/subranking/DtkGetRankingListByHotWordUpRequest.java 47 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/subranking/DtkGetRankingListByReBuyRequest.java 47 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/subranking/DtkGetRankingListByTimeWholeHotRequest.java 47 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/DtkSingleAlbumCommodityResponse.java 48 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/base/DtkApiResponse.java 82 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/base/DtkDiffPageResponse.java 26 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/base/DtkPageResponse.java 24 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/base/DtkSearchPageResponse.java 30 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkActivityLinkResponse.java 36 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkCommodityMaterialsResponse.java 38 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkCouponQueryResponse.java 61 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkCreatTaokoulingResponse.java 23 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkCzmfTransformLinkResponse.java 19 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkFirstOrderGiftMoneyItemResponse.java 28 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkFirstOrderGiftMoneyResponse.java 334 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetCollectionListItemResponse.java 22 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetOrderDetailsResponse.java 27 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetOrderDetailsResultsItemsResponse.java 153 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetOrderDetailsResultsResponse.java 20 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetOwnerGoodsItemResponse.java 43 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetPrivilegeLinkResponse.java 55 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetSuperCategoryResponse.java 21 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetSuperCategorySubResponse.java 18 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGoodsCommentListResponse.java 97 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkJdBatchTransformLinkResponse.java 18 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkJdCommodityTransformLinkResponse.java 19 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkJdLinkAnalysisResponse.java 21 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkJdOrderQueryResponse.java 77 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkJdOrderQueryV2Response.java 88 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkMergeRedEnvelopesResponse.java 36 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkParseContentOriginInfoResponse.java 30 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkParseContentResponse.java 27 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkPddTransformLinkResponse.java 112 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkShopConvertResponse.java 24 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkTbCashGiftResponse.java 23 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkTwdToTwdResponse.java 29 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/MtOrderResponse.java 16 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/ShearPlateDistinguishResponse.java 43 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkBaseItemResponse.java 123 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkGoodsDetailsResponse.java 400 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkGoodsListItemResponse.java 68 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkJdCommodityDetailsResponse.java 59 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkNewestGoodsResponse.java 59 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkPddGoodsDetailsResponse.java 67 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkStaleGoodsByTimeResponse.java 21 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkGetDtkSearchGoodsResponse.java 57 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkGetDtkSearchGoodsResponse1.java 145 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkGetTbServiceImagesResponse.java 18 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkGetTbServiceResponse.java 84 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkGetTop100Response.java 18 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkHotSearchListResponse.java 21 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkJdGoodsTypeResponse.java 22 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkJdUnionQueryResponse.java 88 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkListSuperGoodsResponse.java 67 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkPddGoodsTypeResponse.java 22 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkPddOrderIncrementSearchResponse.java 218 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkPddUnionQueryResponse.java 71 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkSearchSuggestionResponse.java 20 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkTbkScPunishOrderGetResponse.java 53 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkTbkScRelationRefundResponse.java 83 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkActivityCatalogueResponse.java 33 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkActivityGoodsListResponse.java 146 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkAlbumListResponse.java 38 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkBigBrandDiscountResponse.java 77 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkCarouselMapResponseResponse.java 20 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkCatalogueResponse.java 28 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkDdqGoodsListItemResponse.java 62 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkDdqGoodsListResponse.java 19 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkDdqRoundListResponse.java 15 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkExclusiveGoodsListResponse.java 72 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkFriendsCircleListResponse.java 55 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetBrandGoodsListResponse.java 177 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetBrandListResponse.java 64 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetColumnListResponse.java 175 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetHalfPriceDayPriceItemResponse.java 42 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetHalfPriceDayPriceResponse.java 17 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetHalfPriceDayResponse.java 17 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetHalfPriceDaySessionResponse.java 15 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetRankingListMergeResponse.java 58 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetTbTopicListResponse.java 22 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetVideoGoodsCategoryResponse.java 19 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetVideoGoodsListResponse.java 96 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkHighCommissionSelectedResponse.java 70 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkHistoricalNewLowCommodityResponse.java 70 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkJdCommodityDiscountPriceResponse.java 29 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkJdNewYearCommodityResponse.java 24 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkJdOneDollarPurchaseOrderInquiryResponse.java 260 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkListSimilerGoodsByOpenResponse.java 36 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkLiveMaterialGoodsListResponse.java 40 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkMostPopularCommodityListResponse.java 32 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkNineFreeShippingResponse.java 55 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkOpGoodsListResponse.java 39 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkPopularAnchorCommendResponse.java 70 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkPopularGoodsListResponse.java 72 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkPriceTrendHistoricalPriceResponse.java 20 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkPriceTrendResponse.java 39 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkRealTimeListResponse.java 76 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkSubdivisionCategoryListResponse.java 17 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkSuperDiscountGoodsResponse.java 27 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkTipOffResponse.java 45 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkGetHotWordRankingResponse.java 19 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkGetRankingListByHotSearchResponse.java 21 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkGetRankingListByHotWordResponse.java 19 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkGetRankingListByHotWordUpResponse.java 19 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkGetRankingListByReBuyResponse.java 17 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkGetRankingListByTimeWholeHotResponse.java 23 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkRankingBaseResponse.java 47 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsDdCategoryService.java 18 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsDdOrderService.java 15 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsJdCategoryService.java 19 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsJdOrderService.java 16 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsJtkOrderService.java 17 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsMtActitvityService.java 42 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsMtOrderService.java 14 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsOrderService.java 21 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsShopService.java 34 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsDdCategoryServiceImpl.java 37 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsDdOrderServiceImpl.java 67 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsJdCategoryServiceImpl.java 36 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsJdOrderServiceImpl.java 35 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsJtkOrderServiceImpl.java 47 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsMtActitvityServiceImpl.java 155 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsMtOrderServiceImpl.java 30 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsOrderServiceImpl.java 51 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsShopServiceImpl.java 43 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/AESUtils.java 132 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/Assert.java 43 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/DTKUtils.java 157 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/JsonUtil.java 103 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/JtkUtils.java 50 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/MTUtils.java 371 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/ObjectUtil.java 93 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/PddUtils.java 293 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/RequiredCheck.java 18 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/SignMd5Util.java 59 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/SignUtils.java 101 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/TBUtils.java 98 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/vo/JingDongVo.java 31 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/vo/JtkVo.java 17 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/vo/MtfxlmVo.java 28 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/vo/MtlmVo.java 28 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/vo/PddVo.java 26 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/vo/TaoBaoVo.java 26 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-common/src/main/resources/META-INF/MANIFEST.MF 101 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-platform/pom.xml 29 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-platform/src/main/java/com/yami/shop/cps/platform/config/SwaggerConfiguration.java 35 ●●●●● patch | view | raw | blame | history
yami-shop-cps/yami-shop-cps-platform/src/main/java/com/yami/shop/cps/platform/controller/CpsController.java 76 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/pom.xml 26 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-api/pom.xml 28 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/config/SwaggerConfiguration.java 36 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/controller/MyDeliveryController.java 60 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/controller/MyStationOrderController.java 101 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/controller/OrderSelfStationController.java 44 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/controller/StationController.java 170 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/listener/CheckAddrListener.java 77 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/listener/GetUserStationListener.java 43 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/listener/SubmitOrderListener.java 161 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/manager/DeliveryOrderManager.java 91 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/pom.xml 21 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/constant/TransportFreeType.java 45 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/DeliveryOrderItemMapper.java 34 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/DeliveryOrderMapper.java 43 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/OrderSelfStationMapper.java 69 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/SameCityMapper.java 23 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/TranscityFreeMapper.java 20 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/TranscityMapper.java 52 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/TransfeeFreeMapper.java 19 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/TransfeeMapper.java 53 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/TransportMapper.java 47 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/listener/SameCityListener.java 30 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/DeliveryOrder.java 77 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/DeliveryOrderItem.java 47 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/OrderSelfStation.java 73 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/SameCity.java 77 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/Transcity.java 46 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/TranscityFree.java 43 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/Transfee.java 75 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/TransfeeFree.java 68 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/Transport.java 93 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/param/DeliveryOrderItemParam.java 43 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/param/DvyOrderParam.java 24 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/param/OrderItemParam.java 50 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/param/OrderParam.java 185 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/param/StationParam.java 142 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/DeliveryOrderItemService.java 33 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/DeliveryOrderService.java 67 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/OrderSelfStationService.java 67 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/SameCityService.java 63 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/TranscityFreeService.java 22 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/TranscityService.java 22 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/TransfeeFreeService.java 21 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/TransfeeService.java 22 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/TransportManagerService.java 32 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/TransportService.java 60 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/DeliveryOrderItemServiceImpl.java 38 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/DeliveryOrderServiceImpl.java 316 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/OrderSelfStationServiceImpl.java 135 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/SameCityServiceImpl.java 152 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/TranscityFreeServiceImpl.java 29 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/TranscityServiceImpl.java 29 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/TransfeeFreeServiceImpl.java 29 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/TransfeeServiceImpl.java 29 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/TransportManagerServiceImpl.java 258 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/TransportServiceImpl.java 204 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/DeliveryOrderItemMapper.xml 20 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/DeliveryOrderMapper.xml 71 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/OrderSelfStationMapper.xml 93 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/SameCityMapper.xml 20 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/TranscityFreeMapper.xml 12 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/TranscityMapper.xml 40 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/TransfeeFreeMapper.xml 14 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/TransfeeMapper.xml 40 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/TransportMapper.xml 76 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-multishop/pom.xml 29 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/config/SwaggerConfiguration.java 37 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/controller/OrderDeliveryController.java 178 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/controller/SameCityController.java 86 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/controller/StationController.java 229 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/controller/TransportController.java 126 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/listener/GetTransportNamesListener.java 48 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/listener/OrderChangeAddrListener.java 103 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-platform/pom.xml 29 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-platform/src/main/java/com/yami/shop/delivery/platform/config/SwaggerConfiguration.java 37 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-platform/src/main/java/com/yami/shop/delivery/platform/controller/OrderDeliveryController.java 190 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-platform/src/main/java/com/yami/shop/delivery/platform/controller/StationController.java 104 ●●●●● patch | view | raw | blame | history
yami-shop-delivery/yami-shop-delivery-platform/src/main/java/com/yami/shop/delivery/platform/controller/TransportController.java 120 ●●●●● patch | view | raw | blame | history
yami-shop-combo/pom.xml
New file
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>yami-shop</artifactId>
        <groupId>com.yami.shop</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>yami-shop-combo</artifactId>
    <packaging>pom</packaging>
    <modules>
        <module>yami-shop-combo-api</module>
        <module>yami-shop-combo-multishop</module>
        <module>yami-shop-combo-common</module>
        <module>yami-shop-combo-platform</module>
    </modules>
</project>
yami-shop-combo/yami-shop-combo-multishop/pom.xml
New file
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>yami-shop-combo</artifactId>
        <groupId>com.yami.shop</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>yami-shop-combo-multishop</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-combo-common</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-security-multishop</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
    </dependencies>
</project>
yami-shop-combo/yami-shop-combo-multishop/src/main/java/com/yami/shop/combo/multishop/config/SwaggerConfiguration.java
New file
@@ -0,0 +1,36 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.combo.multishop.config;
import lombok.AllArgsConstructor;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * 套餐、赠品
 * @author lanhai
 */
@Configuration("comboSwaggerConfiguration")
@AllArgsConstructor
public class SwaggerConfiguration {
    @Bean
    public GroupedOpenApi comboRestApi() {
        return GroupedOpenApi.builder()
                .group("套餐、赠品接口")
                .packagesToScan("com.yami.shop.combo.multishop.controller")
                .pathsToMatch("/**")
                .build();
    }
}
yami-shop-combo/yami-shop-combo-multishop/src/main/java/com/yami/shop/combo/multishop/controller/ComboController.java
New file
@@ -0,0 +1,92 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.combo.multishop.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.combo.multishop.model.Combo;
import com.yami.shop.combo.multishop.service.ComboProdService;
import com.yami.shop.combo.multishop.service.ComboService;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.multishop.util.SecurityUtils;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Objects;
/**
 * 套餐
 *
 * @author LGH
 * @date 2021-11-02 10:32:48
 */
@RestController
@AllArgsConstructor
@RequestMapping("/shop/combo" )
@Tag(name = "套餐接口")
public class ComboController {
    private final ComboService comboService;
    private final ComboProdService comboProdService;
    @GetMapping("/page" )
    @Operation(summary = "分页查询套餐" , description = "分页查询套餐")
    public ServerResponseEntity<IPage<Combo>> getComboPage(PageParam<Combo> page, Combo combo) {
        combo.setLang(I18nMessage.getDbLang());
        combo.setShopId(SecurityUtils.getShopUser().getShopId());
        IPage<Combo> pageRes = comboService.pageByParam(page, combo);
        return ServerResponseEntity.success(pageRes);
    }
    @GetMapping("/info/{comboId}" )
    @Operation(summary = "通过id查询套餐" , description = "通过id查询套餐")
    public ServerResponseEntity<Combo> getById(@PathVariable("comboId") Long comboId) {
        Combo combo = comboService.getComboWithProdInfoById(comboId);
        if (!Objects.equals(combo.getShopId(), SecurityUtils.getShopUser().getShopId())) {
            // 当前套餐shopId与用户shopId不相等
            throw new YamiShopBindException("yami.combo.not.shop");
        }
        return ServerResponseEntity.success(combo);
    }
    @PostMapping
    @Operation(summary = "新增套餐" , description = "新增套餐")
    public ServerResponseEntity<Void> save(@RequestBody @Valid Combo combo) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        combo.setShopId(shopId);
        comboService.saveInfo(combo);
        comboProdService.removeComboListCache(combo.getMainProdId());
        return ServerResponseEntity.success();
    }
    @PutMapping
    @Operation(summary = "修改套餐" , description = "修改套餐Issued")
    public ServerResponseEntity<Void> updateById(@RequestBody @Valid Combo combo) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        combo.setShopId(shopId);
        comboService.updateInfo(combo);
        return ServerResponseEntity.success();
    }
    @PutMapping("/changeStatus")
    @Operation(summary = "修改套餐状态" , description = "修改套餐状态")
    public ServerResponseEntity<Void> changeStatus(@RequestParam(value = "status") Integer status, @RequestParam(value = "comboId") Long comboId) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        comboService.changeStatus(comboId, shopId, status);
        return ServerResponseEntity.success();
    }
}
yami-shop-combo/yami-shop-combo-multishop/src/main/java/com/yami/shop/combo/multishop/controller/ComboProdController.java
New file
@@ -0,0 +1,97 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.combo.multishop.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.combo.multishop.model.ComboProd;
import com.yami.shop.combo.multishop.service.ComboProdService;
import com.yami.shop.common.annotation.SysLog;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
 * 套餐商品项
 *
 * @author LGH
 * @date 2021-11-02 10:35:08
 */
@RestController
@AllArgsConstructor
@RequestMapping("/seckill/comboProd" )
public class ComboProdController {
    private final ComboProdService comboProdService;
    /**
     * 分页查询
     * @param page 分页对象
     * @param comboProd 套餐商品项
     * @return 分页数据
     */
    @GetMapping("/page" )
    public ServerResponseEntity<IPage<ComboProd>> getComboProdPage(PageParam<ComboProd> page, ComboProd comboProd) {
        return ServerResponseEntity.success(comboProdService.page(page, new LambdaQueryWrapper<ComboProd>()));
    }
    /**
     * 通过id查询套餐商品项
     * @param comboProdId id
     * @return 单个数据
     */
    @GetMapping("/info/{comboProdId}" )
    public ServerResponseEntity<ComboProd> getById(@PathVariable("comboProdId") Long comboProdId) {
        return ServerResponseEntity.success(comboProdService.getById(comboProdId));
    }
    /**
     * 新增套餐商品项
     * @param comboProd 套餐商品项
     * @return 是否新增成功
     */
    @SysLog("新增套餐商品项" )
    @PostMapping
    @PreAuthorize("@pms.hasPermission('seckill:comboProd:save')" )
    public ServerResponseEntity<Boolean> save(@RequestBody @Valid ComboProd comboProd) {
        return ServerResponseEntity.success(comboProdService.save(comboProd));
    }
    /**
     * 修改套餐商品项
     * @param comboProd 套餐商品项
     * @return 是否修改成功
     */
    @SysLog("修改套餐商品项" )
    @PutMapping
    @PreAuthorize("@pms.hasPermission('seckill:comboProd:update')" )
    public ServerResponseEntity<Boolean> updateById(@RequestBody @Valid ComboProd comboProd) {
        return ServerResponseEntity.success(comboProdService.updateById(comboProd));
    }
    /**
     * 通过id删除套餐商品项
     * @param comboProdId id
     * @return 是否删除成功
     */
    @SysLog("删除套餐商品项" )
    @DeleteMapping("/{comboProdId}" )
    @PreAuthorize("@pms.hasPermission('seckill:comboProd:delete')" )
    public ServerResponseEntity<Boolean> removeById(@PathVariable Long comboProdId) {
        return ServerResponseEntity.success(comboProdService.removeById(comboProdId));
    }
}
yami-shop-combo/yami-shop-combo-multishop/src/main/java/com/yami/shop/combo/multishop/controller/GiveawayController.java
New file
@@ -0,0 +1,84 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.combo.multishop.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.Giveaway;
import com.yami.shop.combo.multishop.service.GiveawayService;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.multishop.util.SecurityUtils;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Objects;
/**
 * 赠品
 *
 * @author LGH
 * @date 2021-11-08 13:29:16
 */
@RestController
@AllArgsConstructor
@RequestMapping("/shop/giveaway" )
@Tag(name = "赠品接口")
public class GiveawayController {
    private final GiveawayService giveawayService;
    @GetMapping("/page" )
    @Operation(summary = "分页获取赠品信息" , description = "分页获取赠品信息")
    public ServerResponseEntity<IPage<Giveaway>> getGiveawayPage(PageParam<Giveaway> page, Giveaway giveaway) {
        giveaway.setShopId(SecurityUtils.getShopUser().getShopId());
        IPage<Giveaway> giveawayPage = giveawayService.pageByParam(page, giveaway);
        return ServerResponseEntity.success(giveawayPage);
    }
    @GetMapping("/info/{giveawayId}" )
    @Operation(summary = "通过id查询赠品" , description = "通过id查询赠品")
    public ServerResponseEntity<Giveaway> getById(@PathVariable("giveawayId") Long giveawayId) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        Giveaway giveaway = giveawayService.getInfoById(giveawayId);
        if (!Objects.equals(shopId, giveaway.getShopId())) {
            throw new YamiShopBindException("yami.giveaway.not.on.shop");
        }
        return ServerResponseEntity.success(giveaway);
    }
    @PostMapping
    @Operation(summary = "新增赠品" , description = "新增赠品")
    public ServerResponseEntity<Void> save(@RequestBody @Valid Giveaway giveaway) {
        giveaway.setShopId(SecurityUtils.getShopUser().getShopId());
        giveawayService.saveInfo(giveaway);
        return ServerResponseEntity.success();
    }
    @PutMapping
    @Operation(summary = "修改赠品" , description = "修改赠品")
    public ServerResponseEntity<Void> updateById(@RequestBody @Valid Giveaway giveaway) {
        giveaway.setShopId(SecurityUtils.getShopUser().getShopId());
        giveawayService.updateInfo(giveaway);
        return ServerResponseEntity.success();
    }
    @PutMapping("/changeStatus")
    @Operation(summary = "修改赠品状态" , description = "修改赠品状态")
    public ServerResponseEntity<Void> changeStatus(@RequestParam(value = "status") Integer status, @RequestParam(value = "giveawayId") Long giveawayId) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        giveawayService.changeStatus(giveawayId, shopId, status);
        return ServerResponseEntity.success();
    }
}
yami-shop-combo/yami-shop-combo-multishop/src/main/java/com/yami/shop/combo/multishop/controller/GiveawayProdController.java
New file
@@ -0,0 +1,68 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.combo.multishop.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.GiveawayProd;
import com.yami.shop.bean.model.Product;
import com.yami.shop.combo.multishop.service.GiveawayProdService;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.security.multishop.util.SecurityUtils;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * 套装商品项
 *
 * @author LGH
 * @date 2021-11-08 13:29:16
 */
@RestController
@AllArgsConstructor
@RequestMapping("/shop/giveawayProd" )
@Tag(name = "赠品商品项接口")
public class GiveawayProdController {
    private final GiveawayProdService giveawayProdService;
    /**
     * 分页查询
     * @param page 分页对象
     * @param giveawayProd 套装商品项
     * @return 分页数据
     */
    @GetMapping("/page" )
    @Operation(summary = "分页获取赠品信息" , description = "分页获取赠品信息")
    public ServerResponseEntity<IPage<GiveawayProd>> getGiveawayProdPage(PageParam<GiveawayProd> page, GiveawayProd giveawayProd) {
        return ServerResponseEntity.success(giveawayProdService.page(page, new LambdaQueryWrapper<GiveawayProd>()));
    }
    /**
     * 主赠送商品分页查询
     * @param page 分页对象
     * @param giveawayProd 套装商品项
     * @return 分页数据
     */
    @GetMapping("/mainProdPage" )
    @Operation(summary = "分页获取主赠送商品" , description = "分页获取赠品信息")
    public ServerResponseEntity<IPage<Product>> getMainProdPage(PageParam<Product> page, GiveawayProd giveawayProd) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        giveawayProd.setShopId(shopId);
        return ServerResponseEntity.success(giveawayProdService.getMainProdPage(page, giveawayProd));
    }
}
yami-shop-combo/yami-shop-combo-platform/pom.xml
New file
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>yami-shop-combo</artifactId>
        <groupId>com.yami.shop</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>yami-shop-combo-platform</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-combo-common</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-security-platform</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
    </dependencies>
</project>
yami-shop-combo/yami-shop-combo-platform/src/main/java/com/yami/shop/combo/platform/config/SwaggerConfiguration.java
New file
@@ -0,0 +1,36 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.combo.platform.config;
import lombok.AllArgsConstructor;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * 优惠券
 * @author lanhai
 */
@Configuration("comboSwaggerConfiguration")
@AllArgsConstructor
public class SwaggerConfiguration {
    @Bean
    public GroupedOpenApi comboRestApi() {
        return GroupedOpenApi.builder()
                .group("套餐接口")
                .packagesToScan("com.yami.shop.coupon.platform.controller")
                .pathsToMatch("/**")
                .build();
    }
}
yami-shop-combo/yami-shop-combo-platform/src/main/java/com/yami/shop/combo/platform/task/ComboTask.java
New file
@@ -0,0 +1,48 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.combo.platform.task;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.yami.shop.combo.multishop.service.ComboService;
import com.yami.shop.service.ProductService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
/**
 * @Author lth
 * @Date 2021/11/12 15:07
 */
@Slf4j
@Component("comboTask")
@AllArgsConstructor
public class ComboTask {
    private final ComboService comboService;
    private final ProductService productService;
    private final ApplicationEventPublisher eventPublisher;
    /**
     * 关闭已经结束的套餐活动
     */
    @XxlJob("closeCombo")
    public void closeCombo() {
        comboService.closeComboByEndDate();
    }
    /**
     * 开启到了活动时间未开启的套餐活动
     */
    @XxlJob("enableCombo")
    public void enableCombo(){
        comboService.enableCombo();
    }
}
yami-shop-combo/yami-shop-combo-platform/src/main/java/com/yami/shop/combo/platform/task/GiveawayTask.java
New file
@@ -0,0 +1,49 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.combo.platform.task;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.yami.shop.combo.multishop.service.GiveawayService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
 * @Author lth
 * @Date 2021/11/12 15:07
 */
@Slf4j
@Component("giveawayTask")
@AllArgsConstructor
public class GiveawayTask {
    private final GiveawayService giveawayService;
    /**
     * 关闭已经结束的赠品活动
     */
    @XxlJob("closeGiveaway")
    public void closeGiveaway() {
        giveawayService.closeGiveawayByEndDate();
    }
    /**
     * 启用赠品活动
     */
    @XxlJob("enableGiveaway")
    public void activityStartAndProdChange(){
        XxlJobHelper.log("赠品活动开启");
        giveawayService.startGiveawayActivity();
    }
}
yami-shop-common/pom.xml
New file
@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>yami-shop</artifactId>
        <groupId>com.yami.shop</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>yami-shop-common</artifactId>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>com.luhuiguo</groupId>
            <artifactId>aspose-words</artifactId>
            <version>23.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.qiniu</groupId>
            <artifactId>qiniu-java-sdk</artifactId>
        </dependency>
        <dependency>
            <groupId>com.qcloud</groupId>
            <artifactId>cos_api</artifactId>
        </dependency>
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 开始spring 缓存 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>ma.glasnost.orika</groupId>
            <artifactId>orika-core</artifactId>
        </dependency>
        <dependency>
          <groupId>com.aliyun</groupId>
          <artifactId>aliyun-java-sdk-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.paypal.sdk</groupId>
            <artifactId>rest-api-sdk</artifactId>
        </dependency>
        <dependency>
            <groupId>com.paypal.sdk</groupId>
            <artifactId>checkout-sdk</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-pay</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-miniapp</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-mp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.huaweicloud</groupId>
            <artifactId>esdk-obs-java-bundle</artifactId>
            <version>[3.21.8,)</version>
        </dependency>
        <dependency>
            <groupId>org.lionsoul</groupId>
            <artifactId>ip2region</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>transmittable-thread-local</artifactId>
        </dependency>
        <dependency>
            <groupId>com.xuxueli</groupId>
            <artifactId>xxl-job-core</artifactId>
        </dependency>
    </dependencies>
</project>
yami-shop-common/src/main/java/com/yami/shop/common/annotation/RedisLock.java
New file
@@ -0,0 +1,47 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.annotation;
import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;
/**
 * 使用redis进行分布式锁
 * @author yami
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisLock {
    /**
     * redis锁 名字
     */
    String lockName() default "";
    /**
     * redis锁 key 支持spel表达式
     */
    String key() default "";
    /**
     * 过期毫秒数,默认为5000毫秒
     *
     * @return 轮询锁的时间
     */
    int expire() default 5000;
    /**
     * 超时时间单位
     *
     * @return 秒
     */
    TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}
yami-shop-common/src/main/java/com/yami/shop/common/annotation/SysLog.java
New file
@@ -0,0 +1,24 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.annotation;
import java.lang.annotation.*;
/**
 * 自定义日志注解
 * @author yami
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
    String value() default "";
}
yami-shop-common/src/main/java/com/yami/shop/common/aspect/RedisLockAspect.java
New file
@@ -0,0 +1,74 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.aspect;
import cn.hutool.core.util.StrUtil;
import com.yami.shop.common.annotation.RedisLock;
import com.yami.shop.common.util.SpelUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
 * @author lgh
 */
@Aspect
@Component
public class RedisLockAspect {
    @Autowired
    private RedissonClient redissonClient;
    private static final String REDISSON_LOCK_PREFIX = "redisson_lock:";
    @Around("@annotation(redisLock)")
    public Object around(ProceedingJoinPoint joinPoint, RedisLock redisLock) throws Throwable {
        String spel = redisLock.key();
        String lockName = redisLock.lockName();
        RLock rLock = redissonClient.getLock(getRedisKey(joinPoint,lockName,spel));
        Object result = null;
        try {
            rLock.lock(redisLock.expire(),redisLock.timeUnit());
            //执行方法
            result = joinPoint.proceed();
        } finally {
            if (rLock.isLocked()) {
                rLock.unlock();
            }
        }
        return result;
    }
    /**
     * 将spel表达式转换为字符串
     * @param joinPoint 切点
     * @return redisKey
     */
    private String getRedisKey(ProceedingJoinPoint joinPoint,String lockName,String spel) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();
        Object target = joinPoint.getTarget();
        Object[] arguments = joinPoint.getArgs();
        return REDISSON_LOCK_PREFIX + lockName + StrUtil.COLON + SpelUtil.parse(target,spel, targetMethod, arguments);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/ALiDaYu.java
New file
@@ -0,0 +1,26 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
/**
 * 阿里配置信息
 * @author LGH
 */
@Data
public class ALiDaYu {
    private String accessKeyId;
    private String accessKeySecret;
    private String signName;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/AliOss.java
New file
@@ -0,0 +1,31 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * OSS配置信息
 * @author LGH
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class AliOss extends SwitchBaseModel {
    private String  bucketName;
    private String  accessKeyId;
    private String  accessKeySecret;
    private String  endpoint;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/Alipay.java
New file
@@ -0,0 +1,42 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
/**
 * 支付宝配置
 * @author lgh
 */
@Data
public class Alipay {
    private String appId;
    /**
     * 应用公钥证书
     */
    private String appCertPath;
    /**
     * 支付宝公钥证书
     */
    private String alipayCertPath;
    /**
     * 支付宝根证书
     */
    private String alipayRootCertPath;
    /**
     * 应用私钥
     */
    private String appPrivateKey;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/CDNConfigBean.java
New file
@@ -0,0 +1,33 @@
package com.yami.shop.common.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class CDNConfigBean {
    @Schema(name = "账号appid")
    private String appId;
    @Schema(name = "手机号码")
    private String telephone;
    @Schema(name = "登录密码")
    private String password;
    @Schema(name = "登录url")
    private String url;
    @Schema(name = "设备url")
    private String deviceUrl;
    @Schema(name = "设备流水url")
    private String deviceEarnUrl;
    @Schema(name = "设备分组url")
    private String deviceGroupUrl;
    @Schema(name = "设备释放url")
    private String deviceReleaseUrl;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/CDNDevice.java
New file
@@ -0,0 +1,28 @@
package com.yami.shop.common.bean;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
/**
 * @auth lxw
 * @date 2024/4/25
 * @desc
 */
@Data
public class CDNDevice {
    private String appId;
    private String password;
    private String telephone;
    private String url;
    private String deviceUrl;
    private String deviceEarnUrl;
    private String deviceGroupUrl;
    private String deviceReleaseUrl;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/CdnIncomeRadioConfig.java
New file
@@ -0,0 +1,12 @@
package com.yami.shop.common.bean;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class CdnIncomeRadioConfig {
    private Double supplier;
    private Double platform;
    private Double user;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/ContranctInfo.java
New file
@@ -0,0 +1,78 @@
package com.yami.shop.common.bean;
import lombok.Data;
import java.io.Serializable;
@Data
public class ContranctInfo implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 姓名
     */
    private String name;
    /**
     * 地址
     */
    private String address;
    /**
     * 身份证号
     */
    private String certNo;
    /**
     * 手机号
     */
    private String tel;
    /**
     * 单价
     */
    private String price;
    /**
     * 数量
     */
    private String count;
    /**
     * 总价(小写)
     */
    private String lettTotal;
    /**
     * 总价(大写)
     */
    private String capTotal;
    /**
     * 时间(年)
     */
    private String year;
    /**
     * 时间(月)
     */
    private String month;
    /**
     * 时间(日)
     */
    private String day;
    /**
     * 账号
     */
    private String accNo;
    /**
     * 银行账号
     */
    private String bankNo;
    /**
     * 开户银行
     */
    private String bankName;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/CpsConfig.java
New file
@@ -0,0 +1,28 @@
package com.yami.shop.common.bean;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
 * 大淘客接入的各个平台配置
 * @author zsq
 */
@Data
@TableName("tz_cps_config")
public class CpsConfig {
    @TableId
    private Long id;
    @NotBlank(message="参数名不能为空")
    private String paramKey;
    @NotBlank(message="参数值不能为空")
    private String paramValue;
    @NotBlank(message="备注")
    private String remark;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/DateVO.java
New file
@@ -0,0 +1,24 @@
package com.yami.shop.common.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
 * @auth lxw
 * @date 2024/4/23
 * @desc 统一时间VO
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DateVO {
    // 开始时间
    private Date start;
    // 结束时间
    private Date end;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/Domain.java
New file
@@ -0,0 +1,28 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
/**
 * 域名配置信息
 * @author lgh
 */
@Data
public class Domain {
    private String apiDomainName;
    private String multishopDomainName;
    private String platformDomainName;
    private String resourcesDomainName;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/ExchangeRate.java
New file
@@ -0,0 +1,52 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;
/**
 * 汇率: 本系统货币 和其他币种的兑换比例
 * @author yami
 */
@Data
public class ExchangeRate {
    /** 本系统 1 */
    private BigDecimal currencyLocal;
    /** 美元 */
    private BigDecimal currencyUsd;
    private BigDecimal zero = new BigDecimal("0.0");
    /** 获取美元的汇率 */
    public BigDecimal getUsdExchangeRate() {
        return div(this.currencyUsd,this.currencyLocal,4);
    }
    public BigDecimal getCurExchangeRate() {
        return div(this.currencyLocal, this.currencyUsd, 4);
    }
    private BigDecimal div(BigDecimal v1, BigDecimal v2,int scale) {
        if (Objects.isNull(v1) || Objects.isNull(v2)) {
            return this.zero;
        }
        if (v1.compareTo(this.zero) <=0 || v2.compareTo(this.zero) <= 0) {
            return this.zero;
        }
        return v1.divide(v2,scale, RoundingMode.HALF_EVEN);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/HuaWeiOss.java
New file
@@ -0,0 +1,31 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * OBS配置信息
 * @author LGH
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class HuaWeiOss extends SwitchBaseModel {
    private String  bucketName;
    private String  accessKeyId;
    private String  secretAccessKey;
    private String  endpoint;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/Minio.java
New file
@@ -0,0 +1,30 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * minio配置信息
 * @Author lth
 * @Date 2021/11/11 10:33
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class Minio extends SwitchBaseModel {
    private String  bucketName;
    private String accessKey;
    private String secretKey;
    private String  endpoint;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/PayPal.java
New file
@@ -0,0 +1,44 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
/**
 * Paypal支付配置
 * @author cl
 */
@Data
public class PayPal {
    /**
     *  PayPal 的 clientId
     */
    private String clientId;
    /**
     *  PayPal 的 clientSecret
     */
    private String clientSecret;
    /**
     * sandbox 沙箱or live生产
     */
    private String mode;
    /**
     *  商家邮箱
     */
    private String receiverEmail;
    /**
     * 事件 id
     */
    private String webHookId;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/QCloud.java
New file
@@ -0,0 +1,30 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * 腾讯云cos存储配置信息
 * @author lgh
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class QCloud extends SwitchBaseModel {
    private String secretId;
    private String secretKey;
    private String region;
    private String bucketName;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/Qiniu.java
New file
@@ -0,0 +1,31 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import com.yami.shop.common.enums.QiniuZone;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * 七牛云存储配置信息
 * @author lgh
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class Qiniu extends SwitchBaseModel {
    private String accessKey;
    private String secretKey;
    private String bucket;
    private QiniuZone zone;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/Quick100.java
New file
@@ -0,0 +1,38 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * 快递鸟物流详情查询
 * @author SJL
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class Quick100 extends SwitchBaseModel {
    /**
     * 快递100中顺丰编码
     */
    @JsonIgnore
    public final static String SF_CODE = "shunfeng";
    /**
     * 快递100中丰网速运编码
     */
    @JsonIgnore
    public final static String FENGWANG_CODE = "fengwang";
    private String customer;
    private String key;
    private String reqUrl;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/QuickAli.java
New file
@@ -0,0 +1,31 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * 阿里物流详情查询
 * @Author lth
 * @Date 2021/11/11 14:48
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class QuickAli extends SwitchBaseModel {
    /**
     * 阿里物流中的顺丰编号
     */
    public final static String SF_CODE = "SFEXPRESS";
    private String aliCode;
    private String reqUrl;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/QuickBird.java
New file
@@ -0,0 +1,64 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.EqualsAndHashCode;
/**
 * 快递鸟物流详情查询
 * @author yami
 */
@EqualsAndHashCode(callSuper = true)
public class QuickBird extends SwitchBaseModel {
    /**
     * 快递鸟中顺丰编码
     */
    @JsonIgnore
    public final static String SF_CODE = "SF";
    private String eBusinessID;
    private String appKey;
    private String reqUrl;
    public String geteBusinessID() {
        return eBusinessID;
    }
    public void seteBusinessID(String eBusinessID) {
        this.eBusinessID = eBusinessID;
    }
    public String getAppKey() {
        return appKey;
    }
    public void setAppKey(String appKey) {
        this.appKey = appKey;
    }
    public String getReqUrl() {
        return reqUrl;
    }
    public void setReqUrl(String reqUrl) {
        this.reqUrl = reqUrl;
    }
    @Override
    public String toString() {
        return "QuickBird{" +
                "eBusinessID='" + eBusinessID + '\'' +
                ", appKey='" + appKey + '\'' +
                ", reqUrl='" + reqUrl + '\'' +
                '}';
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/SensitiveWord.java
New file
@@ -0,0 +1,36 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
/**
 * @author Citrus
 * @date 2021/8/6 10:25
 */
public class SensitiveWord {
    /**
     * 敏感词
     */
    private String sensitiveWord;
    public String getSensitiveWord() {
        return sensitiveWord;
    }
    public void setSensitiveWord(String sensitiveWord) {
        this.sensitiveWord = sensitiveWord;
    }
    @Override
    public String toString() {
        return "SensitiveWord{" +
                "sensitiveWord='" + sensitiveWord + '\'' +
                '}';
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/ShopLuckyCoin.java
New file
@@ -0,0 +1,21 @@
package com.yami.shop.common.bean;
import lombok.Data;
@Data
public class ShopLuckyCoin {
    /**
     *  技师需交幸运币
     */
    private Long technician;
    /**
     *  普通商家需交幸运币
     */
    private Long lifeShop;
    /**
     * 生活服务商家需交幸运币
     */
    private Long shop;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/SwitchBaseModel.java
New file
@@ -0,0 +1,25 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
/**
 * 配置开关属性基本类
 *
 * @Author lth
 * @Date 2021/11/17 16:16
 */
@Data
public class SwitchBaseModel {
    private Boolean isOpen;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/SysConfig.java
New file
@@ -0,0 +1,37 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
 * 系统配置信息
 * @author yami
 */
@Data
@TableName("tz_sys_config")
public class SysConfig {
    @TableId
    private Long id;
    @NotBlank(message="参数名不能为空")
    private String paramKey;
    @NotBlank(message="参数值不能为空")
    private String paramValue;
    @NotBlank(message="备注")
    private String remark;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/SysPayConfig.java
New file
@@ -0,0 +1,82 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
/**
 * 系统支付开关配置
 * @author cl
 */
@Data
public class SysPayConfig {
    /**
     *  是否开启支付宝支付
     */
    private Boolean aliPaySwitch;
    /**
     *  是否开启微信支付
     */
    private Boolean wxPaySwitch;
    /**
     *  是否开启余额支付
     */
    private Boolean balancePaySwitch;
    /**
     *  是否开启支付宝支付
     */
    private Boolean payPalSwitch;
    /**
     *  是否开启杉德支付收银台
     */
    private Boolean sdPayPalSwitch;
    /**
     *  是否开启杉德支付二维码
     */
    private Boolean sdQrcodeSwitch;
    /**
     *  是否开启瓜瓜豆支付
     */
    private Boolean sdBeanSwitch;
    /**
     *  是否开启蓝积分支付
     */
//    private Boolean bluePointSwitch;
    /**
     *  是否开启蓝积分+红积分支付
     */
    private Boolean blueRedPointSwitch;
    /**
     *  是否开启蓝积分+余额支付
     */
    private Boolean blueBalancePointSwitch;
    /**
     *  是否开启红积分
     */
    private Boolean redPointSwitch;
    /**
     *  杉德个人支付二维码
     */
    private Boolean sdGrQrcodeSwitch;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/SysProdConfig.java
New file
@@ -0,0 +1,25 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
/**
 * 商品开关配置
 * @author Citrus
 */
@Data
public class SysProdConfig {
    /**
     *  是否开启商品审核
     */
    private Boolean prodAudit;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/SysServiceConfig.java
New file
@@ -0,0 +1,33 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
 * 系统服务条例开关配置
 * @author Citrus
 */
@Data
public class SysServiceConfig {
    @Schema(description = "是否开启服务条款" )
    private Boolean serviceTermsSwitch;
    @Schema(description = "是否开启隐私策略" )
    private Boolean privacyPolicySwitch;
    @Schema(description = "是否开启商家注册协议" )
    private Boolean merchantRegisterProtocolSwitch;
    @Schema(description = "是否开启开店协议" )
    private Boolean shopProtocolSwitch;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/SysUpgradeInfo.java
New file
@@ -0,0 +1,61 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
/**
 * 系统用户
 * @author yami
 */
@Data
@TableName("sys_upgrade_info")
public class SysUpgradeInfo implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 主键
     *
     */
    @TableId
    @Schema(description = "ID" )
    private Long id;
    @Schema(description = "版本更新内容" )
    private String decribe;
    @Schema(description = "apk、wgt包下载地址或者应用市场地址安卓应用市场" )
    private String editionUrl;
    @Schema(description = "是否强制更新 0代表否 1代表是" )
    private String editionForce;
    @Schema(description = "0是整包升级(apk或者appstore或者安卓应用市场)1是wgt升级" )
    private String packageType;
    @Schema(description = "是否发行 @否 1是 为了控制上架应用市场审核时不能弹出热更新框" )
    private String editionIssue;
    @Schema(description = "版本号 最重要的manifest里的版本号" )
    private String editionNumber;
    @Schema(description = "版本名称 manifest里的版本名称" )
    private String editionName;
    @Schema(description = "是否静默更新 0代表否 1代表是" )
    private String editionSilence;
    @Schema(description = "创建时间" )
    private String createTime;
    @Schema(description = "修改时间" )
    private String updateTime;
    @Schema(description = "发布时间" )
    private String releaseTime;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/TaskPageUrl.java
New file
@@ -0,0 +1,13 @@
package com.yami.shop.common.bean;
import lombok.Data;
@Data
public class TaskPageUrl {
    private String prodDetailPage;
    private String registerPage;
    private String promotionPage;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/WxApp.java
New file
@@ -0,0 +1,26 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
/**
 * 微信app参数
 * @author yami
 */
@Data
public class WxApp {
    /**
     * 设置微信原生的appid
     */
    private String appId;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/WxMiniApp.java
New file
@@ -0,0 +1,31 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
/**
 * 微信小程序参数
 * @author yami
 */
@Data
public class WxMiniApp {
    /**
     * 设置微信小程序的appid
     */
    private String appId;
    /**
     * 设置微信小程序的Secret
     */
    private String secret;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/WxMp.java
New file
@@ -0,0 +1,30 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
/**
 * 微信公众号参数
 * @author yami
 */
@Data
public class WxMp {
    /**
     * 设置微信公众号的appid
     */
    private String appId;
    /**
     * 设置微信公众号的Secret
     */
    private String secret;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/WxPay.java
New file
@@ -0,0 +1,70 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean;
import lombok.Data;
/**
 * 微信支付参数
 * @author yami
 */
@Data
public class WxPay {
    public static final Integer VERSION_3 = 3;
    /**
     * 微信支付mchId
     */
    private String mchId;
    /**
     * 微信支付mchKey
     */
    private String mchKey;
    /**
     * 签名类型
     */
    private String signType;
    /**
     * 支付证书路径
     */
    private String keyPath;
    // ======== v3 需要=======
    /**
     * 微信支付版本 2代表用旧的v2支付 3代表用v3支付
     */
    private Integer version;
    /**
     * 证书序列号
     */
    private String certSerialNo;
    /**
     * apiV3秘钥
     */
    private String apiv3Key;
    /**
     * apiv3 商户apiclient_key.pem
     */
    private String privateKeyPath;
    /**
     * apiv3 商户apiclient_cert.pem
     */
    private String privateCertPath;
}
yami-shop-common/src/main/java/com/yami/shop/common/bean/event/GetSensitiveWordEvent.java
New file
@@ -0,0 +1,34 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.bean.event;
import com.yami.shop.common.bean.SensitiveWord;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
 * 获取敏感词配置的事件
 * @author Citrus
 * @date 2021/8/17 11:24
 */
@Data
@AllArgsConstructor
public class GetSensitiveWordEvent {
    /**
     * 配置key
     */
    private String key;
    /**
     * 敏感词
     */
    private SensitiveWord sensitiveWord;
}
yami-shop-common/src/main/java/com/yami/shop/common/config/BigSellerConfig.java
New file
@@ -0,0 +1,74 @@
package com.yami.shop.common.config;
public class BigSellerConfig {
    /** 大淘客(淘宝联盟)相关配置 */
    public static final String CPS_TAOBAO_CONFIG = "CPS_TAOBAO_CONFIG";
    /** 大淘客(京东联盟)相关配置 */
    public static final String CPS_JINGDONG_CONFIG = "CPS_JINGDONG_CONFIG";
    /** 美团联盟相关配置 */
    public static final String CPS_MTLM_CONFIG = "CPS_MTLM_CONFIG";
    /** 美团分销联盟相关配置 */
    public static final String CPS_MTFXLM_CONFIG = "CPS_MTFXLM_CONFIG";
    /** 多多进宝相关配置 */
    public static final String CPS_PDD_CONFIG = "CPS_PDD_CONFIG";
    /** 聚推客联盟配置 */
    public static final String CPS_JTK_CONFIG = "CPS_JTK_CONFIG";
    /** 美团联盟自助取链接口 */
    public static final String CPS_MTLM_GENERATELINK = "https://openapi.meituan.com/api/generateLink";
    /** 美团联盟订单查询接口 */
    public static final String CPS_MTLM_ORDERLIST ="https://openapi.meituan.com/api/orderList";
    /** 美团分销联盟取链接口 */
    public static final String CPS_MTFX_GENERATELINK = "https://union.dianping.com/api/promotion/link";
    /** 美团分销联盟订单获取接口 */
    public static final String CPS_MTFX_ORDERLIST = "https://union.dianping.com/data/promote/verify/item/new";
    /** 美团分销联盟省份查询接⼝ */
    public static final String CPS_MTFX_PROVINCEALL = "https://union.dianping.com/api/province/all";
    /** 美团分销联盟省份查询接⼝ */
    public static final String CPS_JTK_PROVINCEALL = "http://api.act.jutuike.com/mtfx/province_all   ";
    /** 聚推客联盟城市查询接口 */
    public static final String CPS_MTFX_CITYALL = "https://union.dianping.com/api/province/";
    /** 聚推客联盟城市查询接口 */
    public static final String CPS_JTK_CITYALL = "http://api.act.jutuike.com/mtfx/province_cities";
    /** 美团分销联盟城市类目查询接口 */
    public static final String CPS_MTFX_CITYCATEGORY = "https://union.dianping.com/api/city/";
    /** 聚推客联盟城市类目查询接口 */
    public static final String CPS_JTK_CITYCATEGORY = "http://api.act.jutuike.com/mtfx/city_categories";
    /** 团购API-获取某个城市的商圈信息(美团) */
    public static final String CPS_MTFX_MTREGIONS = "https://union.dianping.com/api/mt/city/";
    /** 聚推客团购API-获取某个城市的商圈信息(美团) */
    public static final String CPS_JTK_MTREGIONS = "http://api.act.jutuike.com/mtfx/mt_regions";
    /** 美团分销联盟商品搜索接口 */
  //  public static final String CPS_MTFX_SEARCHDEALS = "https://union.dianping.com/api/search/deals";
    /** 美团分销联盟门店关键信息接口 */
   // public static final String CPS_MTFX_SHOPDETAIL = "https://union.dianping.com/api/shop/detail";
    /** 美团分销联盟门店关键信息接口 */
    public static final String CPS_JTK_UNIONACT = "http://api.jutuike.com/union/act";
    /** 美团分销联盟门店关键信息接口 */
    public static final String CPS_JTK_UNIONORDER = "http://api.jutuike.com/union/orders";
    /** 聚推客 团购订单查询 */
    public static final String CPS_JTK_SEARCHDEALS = "http://api.act.jutuike.com/mtfx/search_deals ";
}
yami-shop-common/src/main/java/com/yami/shop/common/config/Constant.java
New file
@@ -0,0 +1,317 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.config;
import com.yami.shop.common.i18n.LanguageEnum;
/**
 * 常量
 * @author yami
 */
public class Constant {
    /** 超级管理员ID */
    public static final int SUPER_ADMIN_ID = 1;
    /**
     * 自营店id
     */
    public static final long MAIN_SHOP = 1L;
    /**
     * 如果把平台的数据也保存在店铺里面,如分类,热搜之类的,保存的店铺id
     */
    public static final long PLATFORM_SHOP_ID = 0L;
    /**
     * 平台条件标签上限
     */
    public static final long TAG_LIMIT_NUM = 20;
    /**
     * 平台店名称
     */
    public static final String PLATFORM_SHOP_NAME = "官方店";
    /**
     * 积分名称
     */
    public static final String SCORE_CONFIG = "SCORE_CONFIG";
    public static final String SCORE_EXPLAIN = "SCORE_EXPLAIN";
    public static final String LEVEL_SHOW = "LEVEL_SHOW";
    public static final String SCORE_EXPIRE = "SCORE_EXPIRE";
    public static final String SCORE_QUESTION = "SCORE_QUESTION";
    /**
     * 商城缺失sku属性时的字符描述
     */
    public static final String SKU_PREFIX = "规格:";
    public static final String DEFAULT_SKU = "规格";
    /**
     * 成长值名称
     */
    public static final String GROWTH_CONFIG = "GROWTH_CONFIG";
    /** 会员初始等级id*/
    public static final int USER_LEVEL_INIT = 1;
    /** 商家线下核销*/
    public static final int SERVICE_TYPE = 1;
    /** 系统菜单最大id */
    public static final int SYS_MENU_MAX_ID = 30;
    /** 订单超时时间 */
    public static final int ORDER_MAX_TIME = 30;
    /** 订单类型:积分订单 */
    public static final int ORDER_TYPE_SCORE = 3;
    /**
     * 最大确认收货退款时间7天
     */
    public static final int MAX_FINALLY_REFUND_TIME = 7;
    /**
     * 退款最长申请时间,当申请时间过了这个时间段之后,会取消退款申请
     */
    public static final int MAX_REFUND_APPLY_TIME = 7;
    /**
     * 离即将退款超时x小时时提醒
     */
    public static final int MAX_REFUND_HOUR = 12;
    /**
     * 直播间置顶上限个数
     */
    public static final int MAX_TOP_NUM = 10;
    /**
     * 分销佣金结算在确认收货后的时间,维权期过后(7+7+1)
     */
    public static final int DISTRIBUTION_SETTLEMENT_TIME = MAX_FINALLY_REFUND_TIME + MAX_REFUND_APPLY_TIME + 1;
    /**
     * 查询订单成功状态
     */
    public static final String SUCCESS = "SUCCESS";
    /**
     * 一级分类id
     */
    public static final Long CATEGORY_ID = 0L;
    /**
     * 配置名称
     */
    public static final String ALIPAY_CONFIG = "ALIPAY_CONFIG";
    public static final String WXPAY_CONFIG = "WXPAY_CONFIG";
    public static final String QINIU_CONFIG = "QINIU_CONFIG";
    public static final String ALI_OSS_CONFIG = "ALI_OSS_CONFIG";
    public static final String Q_CLOUD_CONFIG = "Q_CLOUD_CONFIG";
    public static final String MINIO_OSS_CONFIG = "MINIO_OSS_CONFIG";
    public static final String HUAWEI_OBS_CONFIG = "HUAWEI_OBS_CONFIG";
    public static final String QUICKBIRD_CONFIG = "QUICKBIRD_CONFIG";
    public static final String QUICK100_CONFIG = "QUICK100_CONFIG";
    public static final String ALI_QUICK_CONFIG = "ALI_QUICK_CONFIG";
    public static final String MA_CONFIG = "MA_CONFIG";
    public static final String MP_CONFIG = "MP_CONFIG";
    public static final String ALIDAYU_CONFIG = "ALIDAYU_CONFIG";
    public static final String DOMAIN_CONFIG = "DOMAIN_CONFIG";
    public static final String MX_APP_CONFIG = "MX_APP_CONFIG";
    public static final String PAYPAL_CONFIG = "PAYPAL_CONFIG";
    public static final String MERCHANT_REGISTER_PROTOCOL_CN = "MERCHANT_REGISTER_PROTOCOL_CN";
    public static final String MERCHANT_REGISTER_PROTOCOL_EN = "MERCHANT_REGISTER_PROTOCOL_EN";
    public static final String SHOP_PROTOCOL_CN = "SHOP_PROTOCOL_CN";
    public static final String SHOP_PROTOCOL_EN = "SHOP_PROTOCOL_EN";
    public static final String SENSITIVE_WORDS = "SENSITIVE_WORDS";
    public static final String CDN_DEVICE_CONFIG = "CDN_DEVICE_CONFIG";
    public static final String TASK_PAGE_URL_CONFIG = "TASK_PAGE_URL_CONFIG";
    public static final String CDN_CONFIG = "CDN_CONFIG";
    public static final String LUCKY_COIN_CONFIG = "LUCKY_COIN_CONFIG";
    /** 汇率配置 */
    public static final String EXCHANGE_RATE_CONFIG = "EXCHANGE_RATE_CONFIG";
    /**
     * 记录缓存名称
     */
    public static final String FLOW_ANALYSIS_LOG = "flowAnalysisLog";
    /**
     * 心跳字符串
     */
    public static final String HEART_BEAT = "HEART_BEAT";
    /**
     * 最大会员等级折扣
     */
    public static final double MAX_LEVEL_DISCOUNT = 10D;
    /**
     * 最小会员等级积分倍率
     */
    public static final double MIN_LEVEL_RATE_SCORE = 1D;
    /**
     * 短信套餐包最大数量
     */
    public static final int MAX_SMS_PACKAGE = 10;
    /**
     * 商品最低金额(非积分商品)
     */
    public static final Double MIN_PRODUCT_AMOUNT = 0.01D;
    /**
     * 店铺最多可以签约的分类数量
     */
    public static final int SIGNING_CATEGORY_LIMIT_NUM = 200;
    /**
     * 店铺签约的品牌数量上限
     */
    public static final int SIGNING_BRAND_LIMIT_NUM = 50;
    /**
     * 店铺可以绑定的银行卡上限
     */
    public static final int SHOP_BANK_CARD_LIMIT_NUM = 5;
    /**
     * 句号(英文符号)
     */
    public static final String PERIOD = ".";
    /**
     * 逗号
     */
    public static final String COMMA = ",";
    /**
     * 中文逗号
     */
    public static final String CN_COMMA = ",";
    /**
     * 冒号
     */
    public static final String COLON = ":";
    /**
     * 零
     */
    public static final Long ZERO_LONG = 0L;
    /**
     * 零
     */
    public static final Double ZERO_DOUBLE = 0D;
    /**
     *
     * 参考CacheKeyPrefix
     * cacheNames 与 key 之间的默认连接字符
     */
    public static final  String UNION = "::";
    /**
     * 默认语言
     */
    public static final Integer DEFAULT_LANG = LanguageEnum.LANGUAGE_ZH_CN.getLang();
    public static final Integer MAX_PAGE_SIZE = 100;
    /**
     * 数据量大时,系统单次处理数据的数量
     */
    public static final Long MAX_DATA_HANDLE_NUM = 10000L;
    /**
     * 分销相关配置
     */
    public static final String DISTRIBUTION_CONFIG = "DISTRIBUTION_CONFIG";
    public static final String DISTRIBUTION_RECRUIT_CONFIG = "DISTRIBUTION_RECRUIT_CONFIG";
    public static final Double MAX_USER_BALANCE = 999999999.99D;
    public static String DISTRIBUTION_REMARKS = "分销配置";
    public static String DISTRIBUTION_RECRUIT_REMARKS = "分销招募推广配置";
    public static final String PURCHASES_ORDER = "PO";
    /**
     * 签名相关
     */
    public static final String PUBLIC_KEY = "publicKey";
    public static final String PRIVATE_KEY = "privateKey";
    /**
     * 系统配置相关
     */
    public static final String PAY_SWITCH_CONFIG = "PAY_SWITCH_CONFIG";
    public static final String SERVICE_SWITCH_CONFIG = "SERVICE_SWITCH_CONFIG";
    public static final String PROD_SWITCH_CONFIG = "PROD_SWITCH_CONFIG";
    /**
     * 店铺最大银行卡数量
     */
    public static final int MAX_SHOP_BANK_CARD = 5;
    /**
     * 使用商品浏览记录进行推荐时,使用的数据数量
     */
    public static final int MAX_PROD_BROWSE_NUM = 50;
    /**
     * 成功状态码
     */
    public static final int SUCCESS_CODE = 200;
    /**
     * xls文件
     */
    public static final String XLS_FILE = "xls";
    /**
     * xlsx文件
     */
    public static final String XLSX_FILE = "xlsx";
    public static final int LAST_FOUR_BY_MOBILE = 4;
    /**
     * 微信最大支付金额
     */
    public static final Double WECHAT_MAX_PAY_AMOUNT = 10000000.00D;
    public static final int MAX_NICK_NAME_LENGTH = 15;
    public static final int EXCEL_BEGIN_ROW = 2;
    /**
     * 统计的最大步骤数
     */
    public static final int MAX_ROUTE_STEP = 10;
    public static final int MAX_MYSQL_STRING_LENGTH = 255;
    /**
     * 秒杀sku缓存key
     */
    public static final String SECKILL_SKU_STOCKS_PREFIX = "SECKILL_SKU_STOCKS_";
    /**
     * 最大轮播图数量
     */
    public static final int MAX_INDEX_IMG_NUM = 10;
    public static final Integer ERROR1 = 475;
    public static final Integer ERROR2 = 476;
    public static final Integer ERROR3 = 477;
    public static final Integer stockWarningMax = 9999999;
    /** 用户收益明细*/
    public static final String USER_DEVICE_INCOME = "USER_DEVICE_INCOME:";
    /** 短剧金币转积分*/
    public static final String RATE_G_SCORE = "RATE_G_SCORE";
}
yami-shop-common/src/main/java/com/yami/shop/common/config/DefaultExceptionHandlerConfig.java
New file
@@ -0,0 +1,82 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.config;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ResponseEnum;
import com.yami.shop.common.response.ServerResponseEntity;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.ArrayList;
import java.util.List;
/**
 * 自定义错误处理器
 * @author LGH
 */
@Slf4j
@Controller
@RestControllerAdvice
public class DefaultExceptionHandlerConfig {
    private static final Logger logger = LoggerFactory.getLogger(DefaultExceptionHandlerConfig.class);
    @ExceptionHandler({ MethodArgumentNotValidException.class, BindException.class })
    public ResponseEntity<ServerResponseEntity<List<String>>> methodArgumentNotValidExceptionHandler(Exception e) {
        logger.error("methodArgumentNotValidExceptionHandler", e);
        List<FieldError> fieldErrors = null;
        if (e instanceof MethodArgumentNotValidException) {
            fieldErrors = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors();
        }
        if (e instanceof BindException) {
            fieldErrors = ((BindException) e).getBindingResult().getFieldErrors();
        }
        if (fieldErrors == null) {
            return ResponseEntity.status(HttpStatus.OK)
                    .body(ServerResponseEntity.fail(ResponseEnum.METHOD_ARGUMENT_NOT_VALID));
        }
        List<String> defaultMessages = new ArrayList<>(fieldErrors.size());
        for (FieldError fieldError : fieldErrors) {
            defaultMessages.add(fieldError.getField() + ":" + fieldError.getDefaultMessage());
        }
        return ResponseEntity.status(HttpStatus.OK)
                .body(ServerResponseEntity.fail(ResponseEnum.METHOD_ARGUMENT_NOT_VALID, defaultMessages));
    }
    @ExceptionHandler(YamiShopBindException.class)
    public ResponseEntity<ServerResponseEntity<?>> unauthorizedExceptionHandler(YamiShopBindException e){
        logger.error("mall4jExceptionHandler", e);
        ServerResponseEntity<?> serverResponseEntity = e.getServerResponseEntity();
        if (serverResponseEntity!=null) {
            return ResponseEntity.status(HttpStatus.OK).body(serverResponseEntity);
        }
        // 失败返回消息 状态码固定为直接显示消息的状态码
        return ResponseEntity.status(HttpStatus.OK).body(ServerResponseEntity.fail(e.getCode(),e.getMessage()));
    }
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ServerResponseEntity<Object>> exceptionHandler(Exception e){
        logger.error("exceptionHandler", e);
        return ResponseEntity.status(HttpStatus.OK).body(ServerResponseEntity.fail(ResponseEnum.EXCEPTION));
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/config/Ip2RegionConfig.java
New file
@@ -0,0 +1,51 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.config;
import cn.hutool.core.io.IoUtil;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
import java.io.InputStream;
/**
 * 获取IP
 * @author yami
 */
@Slf4j
@Configuration
public class Ip2RegionConfig {
    @Bean(destroyMethod = "close")
    public Searcher searcher() throws IOException {
        // 获取ip库路径
        ClassPathResource classPathResource = new ClassPathResource("ip2region.xdb");
        if (classPathResource.getClassLoader() == null){
            log.error("ip2region.xdb 存储路径发生错误,没有被发现");
            return null;
        }
        InputStream inputStream = classPathResource.getInputStream();
        // 1、从 dbPath 加载整个 xdb 到内存。
        byte[] cBuff = IoUtil.readBytes(inputStream);
        // 2、使用上述的 cBuff 创建一个完全基于内存的查询对象。
        Searcher searcher = null;
        try {
            searcher = Searcher.newWithBuffer(cBuff);
        } catch (Exception e) {
            System.out.printf("failed to create content cached searcher: %s\n", e);
        }
        return searcher;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/config/LocalDateTimeSerializerConfig.java
New file
@@ -0,0 +1,41 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.config;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
 * 时间配置
 * @author yami
 */
@Configuration
public class LocalDateTimeSerializerConfig {
    @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
    private String pattern;
    @Bean
    public LocalDateTimeSerializer localDateTimeDeserializer() {
        return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern));
    }
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer());
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/config/MyDetaObjectHandler.java
New file
@@ -0,0 +1,36 @@
package com.yami.shop.common.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
 * @program: feel-generator
 * @description: 自动填充时间
 * @author: Jianfeng LIAN
 * @nickname: 我自然
 * @email : 2580040689@qq.com
 * @github :https://github.com/woizran
 * @date: 2021-06-05 00:28
 **/
@Component
@Slf4j
public class MyDetaObjectHandler implements MetaObjectHandler {
    public void insertFill(MetaObject metaObject) {
        log.info("come to insert fill .........");
        //setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("come to update fill .......");
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/config/MybatisPlusConfig.java
New file
@@ -0,0 +1,67 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.apache.ibatis.type.EnumTypeHandler;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Set;
/**
 * @author LGH
 */
@Configuration
@MapperScan({"com.yami.shop.**.dao"})
public class MybatisPlusConfig {
    /**
     * 逻辑删除插件
     * @return LogicSqlInjector
     */
    @Bean
    @ConditionalOnMissingBean
    public ISqlInjector sqlInjector() {
        return new DefaultSqlInjector();
    }
    /**
     * mybatis-plus插件
     */
    @Bean
    public MybatisPlusInterceptor optimisticLockerInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
    /**
     * 自定义mapper 实体类之间类型处理handler
     * @return
     */
    @Bean
    public ConfigurationCustomizer mybatisConfigurationCustomizer() {
        return configuration -> {
            // 注册自定义 TypeHandler
            configuration.getTypeHandlerRegistry().register(Set.class, EnumTypeHandler.class);
        };
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/config/OrikaConfig.java
New file
@@ -0,0 +1,34 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.config;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * MapperFacade 用于dto ->entity的转换
 * @author lgh
 */
@Configuration
public class OrikaConfig {
    @Bean
    public MapperFactory mapperFactory() {
        return new DefaultMapperFactory.Builder().build();
    }
    @Bean
    public MapperFacade mapperFacade() {
        return mapperFactory().getMapperFacade();
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/config/RedisCacheConfig.java
New file
@@ -0,0 +1,134 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.config;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.yami.shop.common.util.SpringContextUtils;
import org.redisson.codec.JsonJacksonCodec;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
/**
 * @author lgh
 */
@EnableCaching
@Configuration
public class RedisCacheConfig  {
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory,RedisSerializer<Object> redisSerializer) {
        RedisCacheManager redisCacheManager = new RedisCacheManager(
                RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
                // 默认策略,未配置的 key 会使用这个
                this.getRedisCacheConfigurationWithTtl(3600,redisSerializer),
                // 指定 key 策略
                this.getRedisCacheConfigurationMap(redisSerializer)
        );
        redisCacheManager.setTransactionAware(true);
        return redisCacheManager;
    }
    private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap(RedisSerializer<Object> redisSerializer) {
        Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(16);
        redisCacheConfigurationMap.put("product", this.getRedisCacheConfigurationWithTtl(1800,redisSerializer));
        redisCacheConfigurationMap.put("SeckillById", this.getRedisCacheConfigurationWithTtl(10,redisSerializer));
        redisCacheConfigurationMap.put("SeckillByProdId", this.getRedisCacheConfigurationWithTtl(10,redisSerializer));
        redisCacheConfigurationMap.put("SeckillSkuBySeckillId", this.getRedisCacheConfigurationWithTtl(10,redisSerializer));
        redisCacheConfigurationMap.put("SeckillSkuById", this.getRedisCacheConfigurationWithTtl(10,redisSerializer));
        redisCacheConfigurationMap.put("SeckillGetByProdId", this.getRedisCacheConfigurationWithTtl(10,redisSerializer));
        return redisCacheConfigurationMap;
    }
    private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds,RedisSerializer<Object> redisSerializer) {
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
                RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(redisSerializer)
        ).entryTtl(Duration.ofSeconds(seconds));
        return redisCacheConfiguration;
    }
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory,RedisSerializer<Object> redisSerializer) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(redisSerializer);
        redisTemplate.setHashValueSerializer(redisSerializer);
        redisTemplate.setEnableTransactionSupport(false);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
    /**
     * 自定义redis序列化的机制,重新定义一个ObjectMapper.防止和MVC的冲突
     * https://juejin.im/post/5e869d426fb9a03c6148c97e
     */
    @Bean
    public RedisSerializer<Object> redisSerializer() {
        ObjectMapper objectMapper = JsonMapper.builder().disable(MapperFeature.USE_ANNOTATIONS).build();
        // 反序列化时候遇到不匹配的属性并不抛出异常
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 序列化时候遇到空对象不抛出异常
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        // 反序列化的时候如果是无效子类型,不抛出异常
        objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
        // 不使用默认的dateTime进行序列化,
        objectMapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false);
        // 使用JSR310提供的序列化类,里面包含了大量的JDK8时间序列化类
        objectMapper.registerModule(new JavaTimeModule());
        // 启用反序列化所需的类型信息,在属性中添加@class
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.PROPERTY);
        // 配置null值的序列化器
        GenericJackson2JsonRedisSerializer.registerNullValueSerializer(objectMapper, null);
        return new GenericJackson2JsonRedisSerializer(objectMapper);
    }
    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory){
        StringRedisTemplate redisTemplate = new StringRedisTemplate(redisConnectionFactory);
        redisTemplate.setEnableTransactionSupport(false);
        return redisTemplate;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/config/SensitiveWordConfig.java
New file
@@ -0,0 +1,194 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.config;
import java.util.HashSet;
/**
 * @author Citrus
 * @date 2021/8/6 14:32
 */
public class SensitiveWordConfig {
    private static final String SENSITIVE_WORD_SEARCH_URL = "/sys/pconfig/info/SENSITIVE_WORDS";
    private static final String WEBJARS_URL = "/webjars/**";
    private static final String API_DOCS_URL = "/v3/api-docs/**";
    private static final String DOC_URL = "/doc.html";
    private static final String CAPTCHA_URL = "/captcha.jpg";
    private static final String SAVE_CONFIG = "/sys/pconfig/save";
    /**
     * excel
     */
    private static final String SOLD_EXCEL = "/order/order/soldExcel";
    private static final String PL_SOLD_EXCEL = "/platform/order/soldExcel";
    private static final String SCORE_SOLD_EXCEL = "/score/order/soldExcel";
    private static final String IMPORT_USER_MODEL = "/admin/user/importUserModel";
    private static final String ADMIN_FORM_EXCEL = "/admin/form/formExcel";
    private static final String PLATFORM_FORM_EXCEL = "/platform/form/formExcel";
    private static final String EXPORT_USER = "/admin/user/exportUser";
    private static final String UN_DELIVERY_ORDER_EXCEL = "/order/order/unDeliveryOrderExcel";
    private static final String DOWNLOAD_MODEL = "/prod/prod/downloadModel";
    private static final String PLATFORM_EXPORT_PROD = "/platform/search/prod/prodExport";
    private static final String MULTISHOP_EXPORT_PROD = "/admin/search/prod/prodExport";
    private static final String GET_FIN_DETAIL_FORM = "/platform/financialManagement/getFinanDetailForm";
    private static final String GET_PAY_INFO_FORM = "/platform/account_detail/get_pay_info_form";
    private static final String GET_REFUND_INFO_FORM = "/platform/account_detail/get_refund_info_form";
    private static final String EXPORT_SHOP = "/platform/shopDetail/exportShop";
    private static final String EXPORT_SUPPLIER = "/supplier/supplier/exportSupplier";
    private static final String IMPORT_SUPPLIER = "/supplier/supplier/importExcel";
    private static final String MODEL_SUPPLIER = "/supplier/supplier/downLoadModel";
    private static final String MODEL_SUPPLIER_PROD = "/supplier/supplierProd/downLoadModel";
    private static final String IMPORT_SUPPLIER_PROD = "/supplier/supplierProd/importExcel";
    private static final String EXPORT_SUPPLIER_PROD = "/supplier/supplierProd/exportSupplierProd";
    private static final String EXPORT_STOCK_BILL_LOG = "/shop/stockBillLog/exportStockBillLog";
    private static final String EXPORT_STOCK_BILL_LOG_ITEM = "/shop/stockBillLogItem/downloadModel";
    private static final String IMPORT_STOCK_BILL_LOG_ITEM = "/shop/stockBillLogItem/importExcel";
    private static final String STOCK_FLOW_EXPORT_EXCEL = "/shop/stockBillLogItem/exportFlow";
    private static final String EXPORT_SKU = "/sku/exportSkuList";
    private static final String MODEL_TAKE_PROD = "/stock/takeStockProd/downLoadModel";
    private static final String IMPORT_TAKE_PROD = "/stock/takeStockProd/importExcel";
    private static final String EXPORT_TAKE_PROD = "/stock/takeStockProd/exportTakeStockProd";
    private static final String EXPORT_TAKE_STOCK = "/stock/takeStock/exportTakeStock";
    private static final String PURCHASES_ORDER_DOWNLOAD_MODEL = "/purchase/order/downloadModel";
    private static final String PURCHASES_ORDER_EXPORT_EXCEL = "/purchase/order/exportExcel";
    private static final String PURCHASES_ORDER_INBOUND_EXPORT = "/purchase/order/inbound/export";
    private static final String PURCHASES_ORDER_INBOUND_DOWNLOAD_MODEL = "/purchase/order/inbound/downloadModel";
    private static final String PURCHASES_ORDER_INBOUND_EXPORT_EXCEL = "/purchase/order/inbound/exportExcel";
    private static final String DISTRIBUTION_QR_CODE_INVITATION = "/p/distribution/qrCode/invitation";
    private static final String MINI_QR_CODE = "/qrcodeTicket/miniQrCode";
    private static final String CATEGORY_EXPORT = "/prod/category/export";
    private static final String MEMBER_TREND_EXPORT = "/platform/flowCustomerAnalysis/memberTrendExport";
    private static final String FLOW_ANALYSIS_EXPORT = "/platform/flowAnalysis/analysisDataExport";
    private static final String FLOW_TREND_EXPORT = "/platform/flowAnalysis/flowTrendExport";
    private static final String FLOW_SOUR_EXPORT = "/platform/flowAnalysis/flowSourExport";
    private static final String FLOW_USER_ANALYSIS_EXPORT = "/platform/flowUserAnalysis/userAnalysisDataExport";
    private static final String ACCOUNT_DETAIL_EXPORT = "/platform/accountDetail/getPayAndRefundInfoForm";
    private static final String SHOP_WALLET_PLATFORM_EXPORT = "/shop/shopWallet/getShopWalletLogForm";
    private static final String FINANCE_DETAIL_FORM_EXPORT = "/platform/financialManagement/getFinanceDetailForm";
    private static final String MULTISHOP_PROD_EFFECT_EXPORT = "/multishop/prodAnalysis/prodEffectExport";
    private static final String PLATFORM_PROD_EFFECT_EXPORT = "/platform/prodAnalysis/prodEffectExport";
    private static final String PLATFORM_PAY_AMOUNT_TOP_EXPORT = "/platform/prodAnalysis/payAmountTopExport";
    private static final String MULTISHOP_PAY_AMOUNT_TOP_EXPORT = "/multishop/prodAnalysis/payAmountTopExport";
    private static final String PROD_SURVEY_EXPORT = "/platform/prodAnalysis/prodSurveyExport";
    private static final String CUSTOMER_EXPORT = "/user/user/exportCustomer";
    private static final String CUSTOMER_IMPORT = "/user/user/importCustomerExcel";
    private static final String MEMBER_CUSTOMER_TEMPLATE_DOWNLOAD = "/user/user/downloadTemplate";
    private static final String WEB_CONFIG_INFO= "/webConfig/info/*";
    private static final String SYS_WEB_CONFIG_INFO = "/sys/webConfig/info/*";
    private static final String SEARCH_PAGE = "/search/page";
    private static final String API_SHOP_LIST = "/cps/getShopList";
    private static final String SOLD_WITHDRAWAL_EXCEL = "/cdn/Withdrawal/exportWithdrawal";
    private static final String SOLD_WITHDRAWALS_EXCEL = "/cdn/Withdrawal/exportWithdrawals";
    private static final String SOLD_RECHARGE_EXCEL = "/cdn/recharge/exportRecharge";
    /**
     * 商家提现信息
     */
    private static final String EXPORT_SHOPWITHDRAWCASH = "/shop/shopWithdrawCash/exportShopWithdrawCash";
    /**
     * 权限
     */
    private static final String GET_SHOP_MENU = "/sys/shopMenu/nav";
    /**
     * jsapi签名
     */
    private static final String CREATE_JSAPI_SIGNATURE = "/p/wx/jsapi/createJsapiSignature";
    /**
     * 导出待发货的积分订单
     */
    private static final String EXPORT_SCORE_ORDER = "/score/order/unDeliveryOrderExcel";
    /**
     * 导入待发货的积分订单
     */
    private static final String IMPORT_SCORE_ORDER = "/score/order/exportOrderExcel";
    static final HashSet<String> SENSITIVE_WHITE_SET;
    static {
        SENSITIVE_WHITE_SET = new HashSet<>();
        SENSITIVE_WHITE_SET.add(SENSITIVE_WORD_SEARCH_URL);
        SENSITIVE_WHITE_SET.add(WEBJARS_URL);
        SENSITIVE_WHITE_SET.add(API_DOCS_URL);
        SENSITIVE_WHITE_SET.add(DOC_URL);
        SENSITIVE_WHITE_SET.add(CAPTCHA_URL);
        SENSITIVE_WHITE_SET.add(SAVE_CONFIG);
        SENSITIVE_WHITE_SET.add(SOLD_EXCEL);
        SENSITIVE_WHITE_SET.add(PL_SOLD_EXCEL);
        SENSITIVE_WHITE_SET.add(SCORE_SOLD_EXCEL);
        SENSITIVE_WHITE_SET.add(IMPORT_USER_MODEL);
        SENSITIVE_WHITE_SET.add(ADMIN_FORM_EXCEL);
        SENSITIVE_WHITE_SET.add(PLATFORM_FORM_EXCEL);
        SENSITIVE_WHITE_SET.add(EXPORT_USER);
        SENSITIVE_WHITE_SET.add(UN_DELIVERY_ORDER_EXCEL);
        SENSITIVE_WHITE_SET.add(DOWNLOAD_MODEL);
        SENSITIVE_WHITE_SET.add(PLATFORM_EXPORT_PROD);
        SENSITIVE_WHITE_SET.add(MULTISHOP_EXPORT_PROD);
        SENSITIVE_WHITE_SET.add(GET_FIN_DETAIL_FORM);
        SENSITIVE_WHITE_SET.add(GET_PAY_INFO_FORM);
        SENSITIVE_WHITE_SET.add(GET_REFUND_INFO_FORM);
        SENSITIVE_WHITE_SET.add(GET_SHOP_MENU);
        SENSITIVE_WHITE_SET.add(EXPORT_SHOP);
        SENSITIVE_WHITE_SET.add(IMPORT_SUPPLIER);
        SENSITIVE_WHITE_SET.add(EXPORT_SUPPLIER);
        SENSITIVE_WHITE_SET.add(MODEL_SUPPLIER);
        SENSITIVE_WHITE_SET.add(MODEL_SUPPLIER_PROD);
        SENSITIVE_WHITE_SET.add(IMPORT_SUPPLIER_PROD);
        SENSITIVE_WHITE_SET.add(EXPORT_SUPPLIER_PROD);
        SENSITIVE_WHITE_SET.add(EXPORT_STOCK_BILL_LOG);
        SENSITIVE_WHITE_SET.add(EXPORT_STOCK_BILL_LOG_ITEM);
        SENSITIVE_WHITE_SET.add(IMPORT_STOCK_BILL_LOG_ITEM);
        SENSITIVE_WHITE_SET.add(CREATE_JSAPI_SIGNATURE);
        SENSITIVE_WHITE_SET.add(STOCK_FLOW_EXPORT_EXCEL);
        SENSITIVE_WHITE_SET.add(EXPORT_SKU);
        SENSITIVE_WHITE_SET.add(MODEL_TAKE_PROD);
        SENSITIVE_WHITE_SET.add(IMPORT_TAKE_PROD);
        SENSITIVE_WHITE_SET.add(EXPORT_TAKE_PROD);
        SENSITIVE_WHITE_SET.add(EXPORT_TAKE_STOCK);
        SENSITIVE_WHITE_SET.add(PURCHASES_ORDER_DOWNLOAD_MODEL);
        SENSITIVE_WHITE_SET.add(PURCHASES_ORDER_EXPORT_EXCEL);
        SENSITIVE_WHITE_SET.add(PURCHASES_ORDER_INBOUND_EXPORT);
        SENSITIVE_WHITE_SET.add(PURCHASES_ORDER_INBOUND_DOWNLOAD_MODEL);
        SENSITIVE_WHITE_SET.add(PURCHASES_ORDER_INBOUND_EXPORT_EXCEL);
        SENSITIVE_WHITE_SET.add(DISTRIBUTION_QR_CODE_INVITATION);
        SENSITIVE_WHITE_SET.add(MINI_QR_CODE);
        SENSITIVE_WHITE_SET.add(EXPORT_SHOPWITHDRAWCASH);
        SENSITIVE_WHITE_SET.add(EXPORT_SCORE_ORDER);
        SENSITIVE_WHITE_SET.add(IMPORT_SCORE_ORDER);
        SENSITIVE_WHITE_SET.add(CATEGORY_EXPORT);
        SENSITIVE_WHITE_SET.add(MEMBER_TREND_EXPORT);
        SENSITIVE_WHITE_SET.add(FLOW_ANALYSIS_EXPORT);
        SENSITIVE_WHITE_SET.add(FLOW_TREND_EXPORT);
        SENSITIVE_WHITE_SET.add(FLOW_SOUR_EXPORT);
        SENSITIVE_WHITE_SET.add(FLOW_USER_ANALYSIS_EXPORT);
        SENSITIVE_WHITE_SET.add(ACCOUNT_DETAIL_EXPORT);
        SENSITIVE_WHITE_SET.add(SHOP_WALLET_PLATFORM_EXPORT);
        SENSITIVE_WHITE_SET.add(FINANCE_DETAIL_FORM_EXPORT);
        SENSITIVE_WHITE_SET.add(MULTISHOP_PROD_EFFECT_EXPORT);
        SENSITIVE_WHITE_SET.add(PLATFORM_PROD_EFFECT_EXPORT);
        SENSITIVE_WHITE_SET.add(PLATFORM_PAY_AMOUNT_TOP_EXPORT);
        SENSITIVE_WHITE_SET.add(MULTISHOP_PAY_AMOUNT_TOP_EXPORT);
        SENSITIVE_WHITE_SET.add(PROD_SURVEY_EXPORT);
        SENSITIVE_WHITE_SET.add(CUSTOMER_EXPORT);
        SENSITIVE_WHITE_SET.add(CUSTOMER_IMPORT);
        SENSITIVE_WHITE_SET.add(MEMBER_CUSTOMER_TEMPLATE_DOWNLOAD);
        SENSITIVE_WHITE_SET.add(WEB_CONFIG_INFO);
        SENSITIVE_WHITE_SET.add(SYS_WEB_CONFIG_INFO);
        SENSITIVE_WHITE_SET.add(SEARCH_PAGE);
        SENSITIVE_WHITE_SET.add(API_SHOP_LIST);
        SENSITIVE_WHITE_SET.add(SOLD_WITHDRAWAL_EXCEL);
        SENSITIVE_WHITE_SET.add(SOLD_WITHDRAWALS_EXCEL);
        SENSITIVE_WHITE_SET.add(SOLD_RECHARGE_EXCEL);
    }
    private SensitiveWordConfig() {
    }
    public static HashSet<String> getSensitiveWhiteSet() {
        return SENSITIVE_WHITE_SET;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/config/ShopBeanConfig.java
New file
@@ -0,0 +1,29 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.config;
import com.google.gson.Gson;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * 配置
 * @author yami
 */
@Configuration
@AllArgsConstructor
public class ShopBeanConfig {
    @Bean
    public Gson gson(){
        return new Gson();
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/config/SnowflakeConfig.java
New file
@@ -0,0 +1,35 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.config;
import cn.hutool.core.lang.Snowflake;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * 雪花算法订单号生成
 * @author yami
 */
@Configuration
public class SnowflakeConfig {
    @Value("${application.datacenterId}")
    private Long datacenterId;
    @Value("${application.workerId}")
    private Long workerId;
    @Bean
    public Snowflake snowflake() {
        return new Snowflake(workerId, datacenterId);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/config/SwaggerConfig.java
New file
@@ -0,0 +1,95 @@
package com.yami.shop.common.config;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.yami.shop.common.util.PageParam;
import io.swagger.v3.oas.annotations.Hidden;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springdoc.api.annotations.ParameterObject;
import org.springdoc.core.DelegatingMethodParameter;
import org.springdoc.core.GenericParameterService;
import org.springdoc.core.PropertyResolverUtils;
import org.springdoc.core.SpringDocUtils;
import org.springdoc.core.customizers.DelegatingMethodParameterCustomizer;
import org.springdoc.core.providers.ObjectMapperProvider;
import org.springdoc.core.providers.WebConversionServiceProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Configuration
public class SwaggerConfig {
    static {
        SpringDocUtils.getConfig().addAnnotationsToIgnore(JsonIgnore.class);
    }
    @Bean
    public GenericParameterService parameterBuilder(PropertyResolverUtils propertyResolverUtils, Optional<WebConversionServiceProvider> optionalWebConversionServiceProvider, ObjectMapperProvider objectMapperProvider) {
        return new GenericParameterService(propertyResolverUtils, delegatingMethodParameterCustomizer(),
                optionalWebConversionServiceProvider,objectMapperProvider);
    }
    // 解决@ParameterObject和@Hidden, JsonIgnore同时使用不生效的问题
    private Optional<DelegatingMethodParameterCustomizer> delegatingMethodParameterCustomizer() { // NOSONAR
        return Optional.of((originalMethodParam, methodParam) -> {
            // 这个方法类拥有的注解
            Annotation[] annotations = originalMethodParam.getParameterType().getAnnotations();
            boolean typeContainParameterObject = false;
            if (annotations.length > 0) {
                List<? extends Class<? extends Annotation>> annotationTypes = Arrays.stream(annotations).map(Annotation::annotationType).collect(Collectors.toList());
                typeContainParameterObject = annotationTypes.contains(ParameterObject.class);
            }
            if (typeContainParameterObject
                    || (originalMethodParam.hasParameterAnnotations() && originalMethodParam.hasParameterAnnotation(ParameterObject.class))) {
                try {
                    if (isParameterIgnore(originalMethodParam, methodParam)) {
                        Field field = FieldUtils.getDeclaredField(DelegatingMethodParameter.class, "additionalParameterAnnotations", true);
                        try {
                            field.set(methodParam, new Annotation[] {new Hidden() { // NOSONAR
                                @Override
                                public Class<? extends Annotation> annotationType() {
                                    return Hidden.class;
                                }}
                            });
                        } catch (IllegalArgumentException|IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                } catch (NoSuchFieldException | SecurityException e) {
                    e.printStackTrace();
                }
            }
        });
    }
    private boolean isParameterIgnore(MethodParameter originalMethodParam, MethodParameter methodParam) throws NoSuchFieldException, SecurityException {
        String parameterName = StrUtil.isBlank(methodParam.getParameterName())? "":methodParam.getParameterName();
        String fieldName = parameterName.indexOf('.') == -1 ? parameterName : parameterName.substring(0, parameterName.indexOf('.'));
        // 解决mybatis-plus返回的查询参数污染的问题
        if (originalMethodParam.getParameterType().isAssignableFrom(PageParam.class)) {
            if ("searchCount".equals(fieldName)) {
                return true;
            }
        }
        Field declaredField;
        try {
            declaredField = originalMethodParam.getParameterType().getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
            declaredField = originalMethodParam.getParameterType().getSuperclass().getDeclaredField(fieldName);
        }
        return Stream.of(declaredField.getAnnotations())
                .filter(annot -> Arrays.asList(Hidden.class, JsonIgnore.class).contains(annot.annotationType())).count() > 0;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/config/WebMvcConfig.java
New file
@@ -0,0 +1,44 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.config;
import com.yami.shop.common.i18n.YamiLocaleChangeInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
/**
 * @author LGH
 */
@Configuration
public class WebMvcConfig {
    @Autowired
    private YamiLocaleChangeInterceptor localeChangeInterceptor;
    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            //拦截器
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                registry.addInterceptor(localeChangeInterceptor).addPathPatterns("/**");
            }
        };
    }
    @Bean
    public SessionLocaleResolver localeResolver() {
        return new SessionLocaleResolver();
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/config/WebhookConstant.java
New file
@@ -0,0 +1,117 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.config;
import lombok.Data;
/**
 * payPal支付 网络钩子常量
 * @author yami
 */
@Data
public class WebhookConstant {
    public static final String ALL_EVENTS  = "ALL.EVENTS";
    public static final String BILLING_PLAN_ACTIVATED  = "BILLING.PLAN.ACTIVATED";
    public static final String BILLING_PLAN_CREATED  = "BILLING.PLAN.CREATED";
    public static final String BILLING_PLAN_DEACTIVATED  = "BILLING.PLAN.DEACTIVATED";
    public static final String BILLING_PLAN_PRICING_CHANGE_ACTIVATED  = "BILLING.PLAN.PRICING-CHANGE.ACTIVATED";
    public static final String BILLING_PLAN_PRICING_CHANGE_INPROGRESS  = "BILLING.PLAN.PRICING-CHANGE.INPROGRESS";
    public static final String BILLING_PLAN_UPDATED  = "BILLING.PLAN.UPDATED";
    public static final String BILLING_SUBSCRIPTION_ACTIVATED  = "BILLING.SUBSCRIPTION.ACTIVATED";
    public static final String BILLING_SUBSCRIPTION_CANCELLED  = "BILLING.SUBSCRIPTION.CANCELLED";
    public static final String BILLING_SUBSCRIPTION_CREATED = "BILLING.SUBSCRIPTION.CREATED";
    public static final String BILLING_SUBSCRIPTION_EXPIRED = "BILLING.SUBSCRIPTION.EXPIRED";
    public static final String BILLING_SUBSCRIPTION_PAYMENT_FAILED = "BILLING.SUBSCRIPTION.PAYMENT.FAILED";
    public static final String BILLING_SUBSCRIPTION_RE_ACTIVATED = "BILLING.SUBSCRIPTION.RE-ACTIVATED";
    public static final String BILLING_SUBSCRIPTION_RENEWED = "BILLING.SUBSCRIPTION.RENEWED";
    public static final String BILLING_SUBSCRIPTION_SUSPENDED = "BILLING.SUBSCRIPTION.SUSPENDED";
    public static final String BILLING_SUBSCRIPTION_UPDATED = "BILLING.SUBSCRIPTION.UPDATED";
    public static final String CATALOG_PRODUCT_CREATED = "CATALOG.PRODUCT.CREATED";
    public static final String CATALOG_PRODUCT_UPDATED = "CATALOG.PRODUCT.UPDATED";
    public static final String CHECKOUT_CHECKOUT_BUYER_APPROVED = "CHECKOUT.CHECKOUT.BUYER-APPROVED";
    public static final String CHECKOUT_ORDER_APPROVED = "CHECKOUT.ORDER.APPROVED";
    public static final String CHECKOUT_ORDER_COMPLETED = "CHECKOUT.ORDER.COMPLETED";
    public static final String CHECKOUT_ORDER_SAVED = "CHECKOUT.ORDER.SAVED";
    public static final String CHECKOUT_ORDER_VOIDED = "CHECKOUT.ORDER.VOIDED";
    public static final String COMPLIANCE_PROCESS_AGENT_ACTION_INITIATED = "COMPLIANCE.PROCESS.AGENT-ACTION-INITIATED";
    public static final String COMPLIANCE_PROCESS_COMPLETED = "COMPLIANCE.PROCESS.COMPLETED";
    public static final String COMPLIANCE_PROCESS_END_USER_ACTION_REQUIRED = "COMPLIANCE.PROCESS.END-USER-ACTION-REQUIRED";
    public static final String COMPLIANCE_PROCESS_EXEMPTED = "COMPLIANCE.PROCESS.EXEMPTED";
    public static final String COMPLIANCE_PROCESS_FAILED = "COMPLIANCE.PROCESS.FAILED";
    public static final String COMPLIANCE_PROCESS_NOT_APPLIED = "COMPLIANCE.PROCESS.NOT-APPLIED";
    public static final String COMPLIANCE_PROCESS_SYSTEM_ACTION_INITIATED = "COMPLIANCE.PROCESS.SYSTEM-ACTION-INITIATED";
    public static final String DISPUTES_CREATED = "DISPUTES.CREATED";
    public static final String DISPUTES_RESOLVED = "DISPUTES.RESOLVED";
    public static final String DISPUTES_UPDATED = "DISPUTES.UPDATED";
    public static final String CUSTOMER_MANAGED_ACCOUNT_CREATED = "CUSTOMER.MANAGED-ACCOUNT.CREATED";
    public static final String CUSTOMER_MANAGED_ACCOUNT_RISK_ASSESSED = "CUSTOMER.MANAGED-ACCOUNT.RISK-ASSESSED";
    public static final String CUSTOMER_MANAGED_ACCOUNT_UPDATED = "CUSTOMER.MANAGED-ACCOUNT.UPDATED";
    public static final String CUSTOMER_MERCHANT_INTEGRATION_CAPABILITY_UPDATED = "CUSTOMER.MERCHANT-INTEGRATION.CAPABILITY-UPDATED";
    public static final String CUSTOMER_MERCHANT_INTEGRATION_PRODUCT_SUBSCRIPTION_UPDATED = "CUSTOMER.MERCHANT-INTEGRATION.PRODUCT-SUBSCRIPTION-UPDATED";
    public static final String CUSTOMER_MERCHANT_INTEGRATION_SELLER_ALREADY_INTEGRATED = "CUSTOMER.MERCHANT-INTEGRATION.SELLER-ALREADY-INTEGRATED";
    public static final String CUSTOMER_MERCHANT_INTEGRATION_SELLER_CONSENT_GRANTED = "CUSTOMER.MERCHANT-INTEGRATION.SELLER-CONSENT-GRANTED";
    public static final String CUSTOMER_MERCHANT_INTEGRATION_SELLER_EMAIL_CONFIRMED = "CUSTOMER.MERCHANT-INTEGRATION.SELLER-EMAIL-CONFIRMED";
    public static final String CUSTOMER_MERCHANT_INTEGRATION_SELLER_ERROR_BAD_REQUEST = "CUSTOMER.MERCHANT-INTEGRATION.SELLER-ERROR-BAD-REQUEST";
    public static final String CUSTOMER_MERCHANT_INTEGRATION_SELLER_ERROR_INTERNAL_SERVER_ERROR = "CUSTOMER.MERCHANT-INTEGRATION.SELLER-ERROR-INTERNAL-SERVER-ERROR";
    public static final String CUSTOMER_MERCHANT_INTEGRATION_SELLER_ONBOARDING_INITIATED = "CUSTOMER.MERCHANT-INTEGRATION.SELLER-ONBOARDING-INITIATED";
    public static final String CUSTOMER_MERCHANT_INTEGRATION_SELLER_ONBOARDING_STARTED = "CUSTOMER.MERCHANT-INTEGRATION.SELLER-ONBOARDING-STARTED";
    public static final String CUSTOMER_PAYOUT_COMPLETED = "CUSTOMER.PAYOUT.COMPLETED";
    public static final String CUSTOMER_PAYOUT_FAILED = "CUSTOMER.PAYOUT.FAILED";
    public static final String CUSTOMER_USER_PROFILE_PASSWORD_CHANGED = "CUSTOMER.USER-PROFILE.PASSWORD-CHANGED";
    public static final String IDENTITY_AUTHORIZATION_CONSENT_GRANTED = "IDENTITY.AUTHORIZATION-CONSENT.GRANTED";
    public static final String IDENTITY_AUTHORIZATION_CONSENT_REVOKED = "IDENTITY.AUTHORIZATION-CONSENT.REVOKED";
    public static final String INVOICING_INVOICE_CANCELLED = "INVOICING.INVOICE.CANCELLED";
    public static final String INVOICING_INVOICE_CREATED = "INVOICING.INVOICE.CREATED";
    public static final String INVOICING_INVOICE_PAID = "INVOICING.INVOICE.PAID";
    public static final String INVOICING_INVOICE_REFUNDED = "INVOICING.INVOICE.REFUNDED";
    public static final String INVOICING_INVOICE_SCHEDULED = "INVOICING.INVOICE.SCHEDULED";
    public static final String INVOICING_INVOICE_UPDATED = "INVOICING.INVOICE.UPDATED";
    public static final String MERCHANT_ONBOARDING_COMPLETED = "MERCHANT.ONBOARDING.COMPLETED";
    public static final String MERCHANT_PARTNER_CONSENT_REVOKED = "MERCHANT.PARTNER-CONSENT.REVOKED";
    public static final String PAYMENT_NETWORKS_ALTERNATIVE_PAYMENT_COMPLETED = "PAYMENT-NETWORKS.ALTERNATIVE-PAYMENT.COMPLETED";
    public static final String PAYMENT_AUTHORIZATION_CREATED = "PAYMENT.AUTHORIZATION.CREATED";
    public static final String PAYMENT_AUTHORIZATION_VOIDED = "PAYMENT.AUTHORIZATION.VOIDED";
    public static final String PAYMENT_CAPTURE_COMPLETED = "PAYMENT.CAPTURE.COMPLETED";
    public static final String PAYMENT_CAPTURE_DENIED = "PAYMENT.CAPTURE.DENIED";
    public static final String PAYMENT_CAPTURE_PENDING = "PAYMENT.CAPTURE.PENDING";
    public static final String PAYMENT_CAPTURE_REFUNDED = "PAYMENT.CAPTURE.REFUNDED";
    public static final String PAYMENT_CAPTURE_REVERSED = "PAYMENT.CAPTURE.REVERSED";
    public static final String PAYMENT_ORDER_CANCELLED = "PAYMENT.ORDER.CANCELLED";
    public static final String PAYMENT_ORDER_CREATED = "PAYMENT.ORDER.CREATED";
    public static final String PAYMENT_PAYOUTS_ITEM_BLOCKED = "PAYMENT.PAYOUTS-ITEM.BLOCKED";
    public static final String PAYMENT_PAYOUTS_ITEM_CANCELED = "PAYMENT.PAYOUTS-ITEM.CANCELED";
    public static final String PAYMENT_PAYOUTS_ITEM_DENIED = "PAYMENT.PAYOUTS-ITEM.DENIED";
    public static final String PAYMENT_PAYOUTS_ITEM_FAILED = "PAYMENT.PAYOUTS-ITEM.FAILED";
    public static final String PAYMENT_PAYOUTS_ITEM_HELD = "PAYMENT.PAYOUTS-ITEM.HELD";
    public static final String PAYMENT_PAYOUTS_ITEM_REFUNDED = "PAYMENT.PAYOUTS-ITEM.REFUNDED";
    public static final String PAYMENT_PAYOUTS_ITEM_RETURNED = "PAYMENT.PAYOUTS-ITEM.RETURNED";
    public static final String PAYMENT_PAYOUTS_ITEM_SUCCEEDED = "PAYMENT.PAYOUTS-ITEM.SUCCEEDED";
    public static final String PAYMENT_PAYOUTS_ITEM_UNCLAIMED = "PAYMENT.PAYOUTS-ITEM.UNCLAIMED";
    public static final String PAYMENT_PAYOUTSBATCH_DENIED = "PAYMENT.PAYOUTSBATCH.DENIED";
    public static final String PAYMENT_PAYOUTSBATCH_PROCESSING = "PAYMENT.PAYOUTSBATCH.PROCESSING";
    public static final String PAYMENT_PAYOUTSBATCH_SUCCESS = "PAYMENT.PAYOUTSBATCH.SUCCESS";
    public static final String PAYMENT_REFUND_COMPLETED = "PAYMENT.REFUND.COMPLETED";
    public static final String PAYMENT_SALE_COMPLETED = "PAYMENT.SALE.COMPLETED";
    public static final String PAYMENT_SALE_DENIED = "PAYMENT.SALE.DENIED";
    public static final String PAYMENT_SALE_PENDING = "PAYMENT.SALE.PENDING";
    public static final String PAYMENT_SALE_REFUNDED = "PAYMENT.SALE.REFUNDED";
    public static final String PAYMENT_SALE_REVERSED = "PAYMENT.SALE.REVERSED";
    public static final String PAYMENTS_PAYMENT_CREATED = "PAYMENTS.PAYMENT.CREATED";
    public static final String PAYMENT_NETWORKS_INSTRUMENT_LINKED_ACCOUNT_UPDATED = "PAYMENT.NETWORKS.INSTRUMENT.LINKED-ACCOUNT-UPDATED";
    public static final String RISK_DISPUTE_CREATED = "RISK.DISPUTE.CREATED";
    public static final String VAULT_CREDIT_CARD_CREATED = "VAULT.CREDIT-CARD.CREATED";
    public static final String VAULT_CREDIT_CARD_DELETED = "VAULT.CREDIT-CARD.DELETED";
    public static final String VAULT_CREDIT_CARD_UPDATED = "VAULT.CREDIT-CARD.UPDATED";
    public static final String VAULT_PAYMENT_TOKEN_CREATED = "VAULT.PAYMENT-TOKEN.CREATED";
    public static final String VAULT_PAYMENT_TOKEN_DELETED = "VAULT.PAYMENT-TOKEN.DELETED";
    public static final String VAULT_PAYMENT_TOKEN_DELETION_INITIATED = "VAULT.PAYMENT-TOKEN.DELETION-INITIATED";
}
yami-shop-common/src/main/java/com/yami/shop/common/constants/CacheNames.java
New file
@@ -0,0 +1,27 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.constants;
/**
 * @Author lth
 * @Date 2021/8/17 13:09
 */
public interface CacheNames extends ProductCacheNames, ShopCacheNames {
    /**
     *
     * 参考CacheKeyPrefix
     * cacheNames 与 key 之间的默认连接字符
     */
    String UNION = "::";
    /**
     * key内部的连接字符(自定义)
     */
    String UNION_KEY = ":";
}
yami-shop-common/src/main/java/com/yami/shop/common/constants/DictConstant.java
New file
@@ -0,0 +1,116 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.constants;
/**
 * pcdn常量
 *
 * @author yami
 */
public class DictConstant {
    //售卖状态(1:发起售卖,2:处理中 3:交易完成 4:锁定 5取消)
    public static final String PRODUCT_STATUS_1 = "1";
    public static final String PRODUCT_STATUS_2 = "2";
    public static final String PRODUCT_STATUS_3 = "3";
    public static final String PRODUCT_STATUS_4 = "4";
    public static final String PRODUCT_STATUS_5 = "5";
    //求购状态(1:发起求购,2:处理中 3:交易完成 4:锁定 5.取消)
    public static final String WANT_STATUS_1 = "1";
    public static final String WANT_STATUS_2 = "2";
    public static final String WANT_STATUS_3 = "3";
    public static final String WANT_STATUS_4 = "4";
    public static final String WANT_STATUS_5 = "5";
    //订单状态(1:处理中 2:交易成功 3:交易失败 4:订单锁定 5订单取消 6.订单超时)
    public static final String ORDER_STATUS_1 = "1";
    public static final String ORDER_STATUS_2 = "2";
    public static final String ORDER_STATUS_3 = "3";
    public static final String ORDER_STATUS_4 = "4";
    public static final String ORDER_STATUS_5 = "5";
    public static final String ORDER_STATUS_6 = "6";
    //寄售等级
    public static final String TRAN_LEVEL_1 = "1";
    public static final String TRAN_LEVEL_2 = "2";
    public static final String TRAN_LEVEL_3 = "3";
    public static final String TRAN_LEVEL_4 = "4";
    public static final String TRAN_LEVEL_5 = "5";
    public static final String OTRAN_LEVEL_6 = "6";
    public static final String OTRAN_LEVEL_7 = "7";
    //币种(8:流量,9金牛豆 10:幸运池 11:积分)
    public static final Integer WALLET_ID_8 = 8;
    public static final Integer WALLET_ID_9 = 9;
    public static final Integer WALLET_ID_10 = 10;
    public static final Integer WALLET_ID_11 = 11;
    //方式(1:支付宝,2:微信 3:银行卡 )
    public static final String PAY_TYPE_1 = "1";
    public static final String PAY_TYPE_2 = "2";
    public static final String PAY_TYPE_3 = "3";
    //流水类型 25:转换(红--绿)26:刮刮卡绑定兑换绿积分 27:寄售交易 28 金牛豆转换幸运池)
    public static final Integer FLOWNAME_ID_25 = 25;
    public static final Integer FLOWNAME_ID_26 = 26;
    public static final Integer FLOWNAME_ID_27 = 27;
    public static final Integer FLOWNAME_ID_28 = 28;
    public static final Integer FLOWNAME_ID_30 = 30;
    public static final Integer FLOWNAME_ID_50 = 50;
    //激活状态(0:未激活,1:已激活)
    public static final String ACTIVE_STATUS_0 = "0";
    public static final String ACTIVE_STATUS_1 = "1";
    //是否(0:否,1:1)
    public static final String ISNO_0 = "0";
    public static final String ISNO_1 = "1";
    //类型(1,单人,2. 多人)
    public static final String TYPE_1 = "1";
    public static final String TYPE_2 = "2";
    //常量1
    public static final String CONSTANT_1 = "1";
    //常量1
    public static final String CONSTANT_5 = "5";
    public static final String CONSTANT_1000 = "1000";
    public static final String CONSTANT_5000 = "5000";
    public static final String CONSTANT_100 = "100";
    //流量提现手续费
    public static final String RED_WITHDRAWAL_FEE = "red_withdrawal_fee";
    //流量转金牛豆兑换比例(100:110)
    public static final String RED_CHANGE_GREEN_FEE = "red_change_green_fee";
    //提现平台扣除手续费
    public static final String PLAN_HAND_FEE = "plan_hand_fee";
    //平台提现时间(1=1号)
    public static final String PLAT_WITH_TIME = "plat_with_time";
    //寄售模式交易费用
    public static final String TRAN_FEE = "tran_fee";
    //刮刮卡序列号
    public static final String HAND_CARD_SEQ = "hand_card_seq";
    //寄售模式(最大交易额度)
    public static final String MAX_TRAN_NUM = "max_tran_num";
    //寄售模式(最小交易额度)
    public static final String MIN_TRAN_NUM = "min_tran_num";
    //合同模板存放地址
    public static final String CONTRACT_MODEL_URL = "contract_model_url";
    //合同存放地址
    public static final String CONTRACT_URL = "contract_url";
    //金牛豆兑换幸运池比例
    public static final String POINT_SJ_BS = "point_sj_bs";
    //域名
    public static final String DONAME_URL = "https://www.huoxingsuanli.cn";
    //pdf访问路径
    public static final String PDF_URL = "/pdf/concat/";
}
yami-shop-common/src/main/java/com/yami/shop/common/constants/EsCacheNames.java
New file
@@ -0,0 +1,26 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.constants;
/**
 * 配置缓存名字
 *
 * @author lhd
 * @date 2020/12/30
 */
public interface EsCacheNames {
    /**
     * 装修商品ids缓存名称和缓存失效时间
     */
    String RENOVATION_PRODUCT_IDS_CACHE = "renovationProductIdsCache";
    Integer RENOVATION_PRODUCT_IDS_CACHE_TIME = 300;
    Integer RENOVATION_PRODUCT_IDS_LIMIT = 1000;
}
yami-shop-common/src/main/java/com/yami/shop/common/constants/OauthCacheNames.java
New file
@@ -0,0 +1,42 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.constants;
/**
 * @author FrozenWatermelon
 * @date 2020/11/23
 */
public interface OauthCacheNames {
    /**
     * oauth 授权相关key
     */
    String OAUTH_PREFIX = "mall4j_oauth:";
    /**
     * token 授权相关key
     */
    String OAUTH_TOKEN_PREFIX = OAUTH_PREFIX + "token:";
    /**
     * 保存token 缓存使用key
     */
    String ACCESS = OAUTH_TOKEN_PREFIX + "access:";
    /**
     * 刷新token 缓存使用key
     */
    String REFRESH_TO_ACCESS = OAUTH_TOKEN_PREFIX + "refresh_to_access:";
    /**
     * 根据uid获取保存的token key缓存使用的key
     */
    String UID_TO_ACCESS = OAUTH_TOKEN_PREFIX + "uid_to_access:";
}
yami-shop-common/src/main/java/com/yami/shop/common/constants/OrderCacheNames.java
New file
@@ -0,0 +1,63 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.constants;
/**
 * @author FrozenWatermelon
 * @date 2020/11/23
 */
public interface OrderCacheNames {
    /**
     *
     * 参考CacheKeyPrefix
     * cacheNames 与 key 之间的默认连接字符
     */
    String UNION = "::";
    /**
     * 普通确认订单信息缓存
     */
    String ORDER_CONFIRM_KEY = "order:confirm:";
    /**
     * 普通订单uuid
     */
    String ORDER_CONFIRM_UUID_KEY = "order:uuid_confirm:";
    /**
     * 拼团确认订单信息缓存
     */
    String GROUP_ORDER_CONFIRM_KEY = "group_order:confirm:";
    /**
     * 拼团订单uuid
     */
    String GROUP_ORDER_CONFIRM_UUID_KEY = "group_order:uuid_confirm:";
    /**
     * 秒杀确认订单信息缓存
     */
    String SECKILL_ORDER_CONFIRM_KEY = "seckill_order:confirm:";
    /**
     * 秒杀订单uuid
     */
    String SECKILL_ORDER_CONFIRM_UUID_KEY = "seckill_order:uuid_confirm:";
    /**
     * 积分确认订单信息缓存
     */
    String SCORE_ORDER_CONFIRM_KEY = "score_order:confirm:";
    /**
     * 积分订单uuid
     */
    String SCORE_ORDER_CONFIRM_UUID_KEY = "score_order:uuid_confirm:";
}
yami-shop-common/src/main/java/com/yami/shop/common/constants/PCDNConstant.java
New file
@@ -0,0 +1,26 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.constants;
/**
 * pcdn常量
 *
 * @author yami
 */
public class PCDNConstant {
    // pcdn token key
    public static final String PCDN_TOKEN_CONSTANT = "pcdn-key:";
    // pcdn api接口返回成功状态
    public static final Integer PCDN_API_RESPONSE_CODE = 1000;
}
yami-shop-common/src/main/java/com/yami/shop/common/constants/PaypalConstant.java
New file
@@ -0,0 +1,264 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.constants;
/**
 * paypal支付常量
 * @author yami
 */
public class PaypalConstant {
    /**
     * PayPal 取消支付回调地址
     */
    public static final String PAYPAL_CANCEL_URL = "/notice/pay/paypal/cancel";
    /**
     * PayPal 取消支付回调地址
     */
    public static final String PAYPAL_SUCCESS_URL = "/notice/pay/paypal/success";
    /**
     * 当前货币币种简称, 默认为人名币的币种 EUR CNY USD
     * 默认为美元币种
     */
    public static final String CURRENTCY = "USD";
    /**
     * approval_url 验证url
     */
    public static final String APPROVAL_URL = "approval_url";
    /**
     * approved 获准
     */
    public static final String APPROVED = "approved";
    /**
     * sandbox 沙箱or live生产
     */
    public static final String PAYPAL_MODE = "live";
    public static final String CAPTURE = "CAPTURE";
    /**
     * 该标签将覆盖PayPal网站上PayPal帐户中的公司名称
     */
    public static final String BRANDNAME = "Supernote";
    /**
     * LOGIN。当客户单击PayPal Checkout时,客户将被重定向到页面以登录PayPal并批准付款。
     * BILLING。当客户单击PayPal Checkout时,客户将被重定向到一个页面,以输入信用卡或借记卡以及完成购买所需的其他相关账单信息
     * NO_PREFERENCE。当客户单击“ PayPal Checkout”时,将根据其先前的交互方式将其重定向到页面以登录PayPal并批准付款,或重定向至页面以输入信用卡或借记卡以及完成购买所需的其他相关账单信息使用PayPal。
     * 默认值:NO_PREFERENCE
     */
    public static final String LANDINGPAGE = "NO_PREFERENCE";
    /**
     * CONTINUE。将客户重定向到PayPal付款页面后,将出现“ 继续”按钮。当结帐流程启动时最终金额未知时,请使用此选项,并且您想将客户重定向到商家页面而不处理付款。
     * PAY_NOW。将客户重定向到PayPal付款页面后,出现“ 立即付款”按钮。当启动结帐时知道最终金额并且您要在客户单击“ 立即付款”时立即处理付款时,请使用此选项。
     */
    public static final String USERACTION = "PAY_NOW";
    /**
     * GET_FROM_FILE。使用贝宝网站上客户提供的送货地址。
     * NO_SHIPPING。从PayPal网站编辑送货地址。推荐用于数字商品
     * SET_PROVIDED_ADDRESS。使用商家提供的地址。客户无法在PayPal网站上更改此地址
     */
    public static final String SHIPPINGPREFERENCE = "SET_PROVIDED_ADDRESS";
    public static final String COMPLETED = "COMPLETED";
    /**
     * 交易异常
     */
    public static final String FAILURE = "failure";
    /**
     * 交易成功
     */
    public static final String SUCCESS = "success";
    /**
     * ipn回调。支付成功
     */
    public static final String PAYMENT_STATUS_COMPLETED = "Completed";
    /**
     * ipn回调。退款成功
     */
    public static final String PAYMENT_STATUS_REFUNDED = "Refunded";
    /**
     * ipn回调。待定
     */
    public static final String PAYMENT_STATUS_PENDING = "Pending";
    /**
     * ipn回调,付款因退款或其他类型的冲销而被冲销。资金已从您的帐户余额中删除,并退还给买方
     */
    public static final String PAYMENT_STATUS_REVERSED = "Reversed";
    /**
     *  ipn回调, 撤销已被取消。例如,您赢得了与客户的纠纷,并且撤回的交易资金已退还给您
     */
    public static final String PAYMENT_STATUS_CANCELED_REVERSAL = "Canceled_Reversal";
    /**
     *  ipn回调,付款被拒绝
     */
    public static final String PAYMENT_STATUS_DENIED = "Denied";
    /**
     *  ipn回调, 此授权已过期,无法捕获
     */
    public static final String PAYMENT_STATUS_EXPIRED = "Expired";
    /**
     *  ipn回调,  德国的ELV付款是通过Express Checkout进行的
     */
    public static final String PAYMENT_STATUS_CREATED = "Created";
    /**
     * ipn回调, 付款失败。仅当付款是通过您客户的银行帐户进行的。
     */
    public static final String PAYMENT_STATUS_FAILED = "Failed";
    /**
     *   ipn回调,付款已被接受
     */
    public static final String PAYMENT_STATUS_PROCESSED = "Processed";
    /**
     *   ipn回调,此授权已失效
     */
    public static final String PAYMENT_STATUS_VOIDED = "Voided";
    //订单状态
    /**
     * 1、支付完成;捕获的付款的资金已记入收款人的PayPal帐户
     * 2、退款完成;该交易的资金已记入客户的帐户
     */
    public static final String STATE_COMPLETED = "COMPLETED";
    /**
     * 部分退款;少于所捕获付款金额的金额已部分退还给付款人。
     */
    public static final String STATE_PARTIALLY_REFUNDED = "PARTIALLY_REFUNDED";
    /**
     * 1、支付待定;捕获的付款资金尚未记入收款人的PayPal帐户。有关更多信息请参见status.details。
     * 2、退款待定;有关更多信息,请参见status_details.reason。
     */
    /**
     * 支付待定:
     * capture_status_details
     * reason 枚举
     * 捕获的付款状态为PENDING或DENIED的原因。可能的值为:
     * BUYER_COMPLAINT。付款人与贝宝(PayPal)对此捕获的付款提出了争议。
     * CHARGEBACK。响应于付款人与用于支付此已捕获付款的金融工具的发行人对此已捕获的付款提出异议,已收回的资金被撤回。
     * ECHECK。由尚未结清的电子支票支付的付款人。
     * INTERNATIONAL_WITHDRAWAL。访问您的在线帐户。在您的“帐户概览”中,接受并拒绝此笔付款。
     * OTHER。无法提供其他特定原因。有关此笔付款的更多信息,请在线访问您的帐户或联系PayPal。
     * PENDING_REVIEW。捕获的付款正在等待人工审核。
     *(手动收取)RECEIVING_PREFERENCE_MANDATES_MANUAL_ACTION。收款人尚未为其帐户设置适当的接收首选项。有关如何接受或拒绝此付款的更多信息,请在线访问您的帐户。通常在某些情况下提供此原因,例如,当所捕获付款的货币与收款人的主要持有货币不同时。
     * REFUNDED。收回的资金已退还。
     * TRANSACTION_APPROVED_AWAITING_FUNDING。付款人必须将这笔付款的资金汇出。通常,此代码适用于手动EFT。
     * UNILATERAL。收款人没有PayPal帐户。
     * VERIFICATION_REQUIRED。收款人的PayPal帐户未通过验证。
     */
    /**
     * 退款待定
     * 退款具有“PENDING”或“FAILED”状态的原因。 可能的值为:
     * ECHECK。客户的帐户通过尚未结清的eCheck进行注资。
     */
    public static final String STATE_PENDING = "PENDING";
    /**
     * 退款;大于或等于此捕获的付款金额的金额已退还给付款人
     */
    public static final String STATE_REFUNDED = "REFUNDED";
    /**
     * 支付拒绝
     */
    public static final String STATE_DENIED = "DENIED";
    /**
     * 退款失败
     */
    public static final String STATE_FAILED = "FAILED";
    /**
     * 争议状态
     */
    public static final String BUYER_COMPLAINT = "BUYER_COMPLAINT";
    /**
     * 沙箱环境请求网关地址
     */
    public static final String SANDBOX = "https://api-m.sandbox.paypal.com";
    /**
     * 生产环境请求网关地址
     */
    public static final String LIVE = "https://api.paypal.com";
    /**
     * 添加物流信息请求路径
     */
    public static final String ADD_TRACK_URL = "/v1/shipping/trackers-batch";
    /**
     * 修改物流信息请求路径
     */
    public static final String UPDATE_TRACK_URL = "/v1/shipping/trackers/";
    public static final String REFUNDED = "Refunded";
    public static final String PENDING = "Pending";
    public static final String VERIFIED = "VERIFIED";
    /**
     * 验签地址
     * 沙箱: https://www.sandbox.paypal.com/cgi-bin/webscr
     * 正式: https://www.paypal.com/cgi-bin/webscr
     */
    public final static String PAY_URL = "https://www.sandbox.paypal.com/cgi-bin/webscr";
    public final static String CMD_XCLICK = "_xclick";
    public final static String CMD_NOTIFY_VALIDATE = "_notify-validate";
    /** 生成发票二维码地址 */
    public final static String INVOICES_QR_CODE_URL = "/v2/invoicing/invoices/{invoice_id}/generate-qr-code";
    /** 生成发票二维码 的高度*/
    public final static Integer INVOICES_QR_CODE_HEIGHT = 400;
    /** 生成发票二维码 的宽度*/
    public final static Integer INVOICES_QR_CODE_WIDTH = 400;
    /** payPal网络钩子超出限制 */
    public final static String WEBHOOK_NUMBER_LIMIT_EXCEEDED = "WEBHOOK_NUMBER_LIMIT_EXCEEDED";
    //币种
    public final static String WALLET_ID_1 = "1";
    public final static String WALLET_ID_2 = "2";
    public final static String WALLET_ID_3 = "3";
    public final static String WALLET_ID_4 = "4";
    public final static String WALLET_ID_5 = "5";
    public final static String WALLET_ID_6 = "6";
    public final static String WALLET_ID_7 = "7";
    public final static String WALLET_ID_8 = "8";
    //支付方式
    public final static String PAY_TYPE_1 = "1";
    public final static String PAY_TYPE_2 = "2";
    public final static String PAY_TYPE_3 = "3";
    public final static String PAY_TYPE_4 = "4";
    public final static String PAY_TYPE_5 = "5";
    public final static String PAY_TYPE_6 = "6";
    public final static String PAY_TYPE_7 = "7";
    public final static String PAY_TYPE_8 = "8";
    public final static String PAY_TYPE_9 = "9";
    public final static String PAY_TYPE_10 = "10";
    public final static String PAY_TYPE_11 = "11";
    public final static String PAY_TYPE_12 = "12";
    public final static String PAY_TYPE_13 = "13";
    public final static String PAY_TYPE_14 = "14";
    public final static String PAY_TYPE_15 = "15";
    public final static String PAY_TYPE_16 = "16";
    public final static String PAY_TYPE_17 = "17";
    public final static String PAY_TYPE_18 = "18";
}
yami-shop-common/src/main/java/com/yami/shop/common/constants/ProductCacheNames.java
New file
@@ -0,0 +1,71 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.constants;
/**
 * @author FrozenWatermelon
 * @date 2020/11/23
 */
public interface ProductCacheNames {
    /**
     * 前缀
     */
    String PRODUCT_PREFIX = "mall4cloud_product:";
    /**
     * 用户端分类列表缓存key
     */
    String CATEGORY_INFO = PRODUCT_PREFIX + "category:info:";
    /**
     * 根据店铺id和上级id,获取分类列表缓存key
     */
    String CATEGORY_RATE = PRODUCT_PREFIX + "category:category_rate:";
    /**
     * 购物车商品数量
     */
    String SHOP_CART_ITEM_COUNT = "shop_cart:count:";
    /**
     * 获取商品的缓存key
     */
    String PRODUCT_KEY = "product";
    /**
     * 获取商品扩展信息的缓存key
     */
    String PROD_EXTENSION_INFO_KEY = "prodExtensionInfo";
    /**
     * 根据skuId获取sku的缓存key
     */
    String SKU_KEY = "sku";
    /**
     * 获取sku列表的缓存key
     */
    String SKU_LIST_KEY = "skuList";
    /**
     * 获取sku库存列表的缓存key
     */
    String LIST_SKU_STOCK_KEY = "listSkuStock";
    /**
     * 店铺获取签约的所有分类列表
     */
    String LIST_SIGNING_CATEGORY_BY_SHOP_ID = "category_shop:list_signing:";
    /**
     * 店铺签约的可用分类列表(发布商品时使用)
     */
    String LIST_AVAILABLE_SIGNING_CATEGORY_BY_SHOP_ID = "category_shop:list_available:";
}
yami-shop-common/src/main/java/com/yami/shop/common/constants/ResultMsg.java
New file
@@ -0,0 +1,49 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.constants;
/**
 * pcdn常量
 *
 * @author yami
 */
public class ResultMsg {
    //流量不足
    public static final String REDRUDY_INSU = "流量不足!";
    //金牛豆不足
    public static final String GREEN_INSU = "金牛豆不足!";
    //单日取消订单已经达到三次,请明天开始交易
    public static final String DAY_CACEL_INSU = "单日取消订单已经达到三次,请明天开始交易!";
    //流量转换金牛豆
    public static final String RED_TRAN_GREEN = "流量转换金牛豆";
    //流量转换金牛豆
    public static final String C2C_TRAN = "c2c交易";
    //绑定刮刮卡兑换金牛豆
    public static final String BAND_TRAN_GREEN = "绑定刮刮卡兑换金牛豆";
    //流量转换金牛豆
    public static final String ACTIVE_TRAN_ADVERT = "金牛豆激活广告";
    //流量转换金牛豆
    public static final String GREEM_TRAN_LUCK = "金牛豆转换幸运池";
    //流量已抢空,无法发起订单!
    public static final String RED_TRAN_EMPTY = "流量已抢空,无法发起订单!";
    //有业务正在处理,无法取消!
    public static final String BUSSINESS_BEING = "有业务正在处理,无法取消!";
    //用户锁定状态,无法操作!
    public static final String USER_LOCK_CANOT_OPER = "用户锁定状态,无法操作!";
    //当前用户等级无法操作!
    public static final String USER_LEVE_CANOT_OPER = "当前用户等级无法操作!";
    //请先进行实名认证!
    public static final String USER_AUTHCATION= "请先进行实名认证!";
    public static final String EXCHANGE_MONEYIS_EMPTY= "兑换金额为空!";
    public static final String ERROR_HUNDRED= "请输入整百的倍数!";
}
yami-shop-common/src/main/java/com/yami/shop/common/constants/ShopCacheNames.java
New file
@@ -0,0 +1,18 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.constants;
/**
 * @Author lth
 * @Date 2021/8/17 13:09
 */
public interface ShopCacheNames {
    String SHOP_DETAIL_ID_KEY = "shop_detail";
}
yami-shop-common/src/main/java/com/yami/shop/common/enums/CodeBaseEnum.java
New file
@@ -0,0 +1,11 @@
package com.yami.shop.common.enums;
/**
 * 统一的enum接口
 * 实现该接口 统一处理枚举类和实体类映射
 */
public interface CodeBaseEnum {
    Integer getValue();
    String getDesc();
}
yami-shop-common/src/main/java/com/yami/shop/common/enums/EsRenovationProductSortEnum.java
New file
@@ -0,0 +1,68 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.enums;
/**
 * 装修商品排序
 * @author lhd
 * @date 2023/01/30
 */
public enum EsRenovationProductSortEnum {
    /**
     * 上架时间升序
     */
    CREATE_TIME_ASC(0, "createTime"),
    /**
     * 上架时间降序
     */
    CREATE_TIME_DESC(1, "createTime"),
    /**
     * 销量倒序
     */
    SALE_NUM_DESC(2, "saleNum"),
    /**
     * 销量正序
     */
    SALE_NUM_ASC(3, "saleNum"),
    /**
     * 评论数量倒序
     */
    COMMENT_NUM_DESC(4, "commentNum"),
    /**
     * 评论数量正序
     */
    COMMENT_NUM_ASC(5, "commentNum"),
    ;
    private final Integer value;
    private final String param;
    public Integer value() {
        return value;
    }
    EsRenovationProductSortEnum(Integer value, String param) {
        this.value = value;
        this.param = param;
    }
    public String param() {
        return param;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/enums/LuckyCoinEnum.java
New file
@@ -0,0 +1,26 @@
package com.yami.shop.common.enums;
import lombok.Data;
/**
 * 幸运币
 */
public enum LuckyCoinEnum {
    /**
     * 应交最低幸运币数额
     */
    TechnicianAmount(3000L),ShopAmount(4000L),LifeShopAmount(5000L);
    private final Long value;
    // 构造方法
    LuckyCoinEnum(Long value) {
        this.value = value;
    }
    // Getter方法
    public Long getValue() {
        return value;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/enums/PayType.java
New file
@@ -0,0 +1,105 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.enums;
import java.util.Objects;
/**
 * 支付类型
 * @author yami
 */
public enum PayType {
    /** 积分支付*/
    SCOREPAY(0,"积分支付"),
    /** 微信支付*/
    WECHATPAY(1,"小程序支付"),
    /** 支付宝*/
    ALIPAY(2,"支付宝"),
    /** 微信扫码支付*/
    WECHATPAY_SWEEP_CODE(3,"微信扫码支付"),
    /** 微信H5支付*/
    WECHATPAY_H5(4,"微信H5支付"),
    /** 微信公众号*/
    WECHATPAY_MP(5,"微信公众号支付"),
    /** 支付宝H5支付*/
    ALIPAY_H5(6,"支付宝H5支付"),
    /** 支付宝APP支付*/
    ALIPAY_APP(7,"支付宝APP支付"),
    /** 微信APP支付*/
    WECHATPAY_APP(8,"微信APP支付"),
    /** 余额支付*/
    BALANCE(9,"余额支付"),
    /** paypal支付 */
    PAYPAL(10,"paypal支付"),
    /** 杉德付款码支付(主扫) */
    SDPAY(11,"杉德付款码支付"),
    /** 杉德收银台统一下单 */
    SDSYTPAY(12,"杉德收银台统一下单"),
    /** 瓜瓜豆支付 **/
    BEAN(13,"瓜瓜豆支付"),
    BLUEPOINT(14,"蓝积分支付"),
    BLUEREDPOINT(15,"蓝积分+红积分支付"),
    BLUEBALANCEPOINT(16,"蓝积分+余额支付"),
    REDPOINT(17,"红积分支付"),
    SDPEOPLEPAY(18,"杉德宝支付");
    private final Integer num;
    private final String payTypeName;
    public Integer value() {
        return num;
    }
    public String payTypeName() {return payTypeName;}
    PayType(Integer num,String payTypeName){
        this.num = num;
        this.payTypeName = payTypeName;
    }
    public static PayType instance(Integer value) {
        PayType[] enums = values();
        for (PayType statusEnum : enums) {
            if (statusEnum.value().equals(value)) {
                return statusEnum;
            }
        }
        return null;
    }
    public static boolean isWxPay(PayType payType) {
        return (Objects.equals(payType, PayType.WECHATPAY)
                || Objects.equals(payType, PayType.WECHATPAY_SWEEP_CODE)
                || Objects.equals(payType, PayType.WECHATPAY_H5)
                || Objects.equals(payType, PayType.WECHATPAY_MP)
                || Objects.equals(payType, PayType.WECHATPAY_APP));
    }
    public static boolean isAliPay(PayType payType) {
        return (Objects.equals(payType, PayType.ALIPAY_H5)
                || Objects.equals(payType, PayType.ALIPAY)
                || Objects.equals(payType, PayType.ALIPAY_APP));
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/enums/QiniuZone.java
New file
@@ -0,0 +1,48 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.enums;
/**
 * 七牛云zone的选择
 * @author LGH
 */
public enum QiniuZone {
    /**
     * 华东机房相关
     */
    HUA_DONG(),
    /**
     * 华北机房相关
     */
    HUA_BEI(),
    /**
     * 华南机房相关
     */
    HUA_NAN(),
    /**
     * 北美机房相关
     */
    BEI_MEI(),
    /**
     * 新加坡机房相关
     */
    XIN_JIA_PO(),
    ;
    QiniuZone(){
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/enums/StatusEnum.java
New file
@@ -0,0 +1,89 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.enums;
import java.util.Objects;
/**
 * 状态
 * @author yxf
 * @date 2020/11/20
 */
public enum StatusEnum {
    /**
     * 删除 (逻辑删除)
     */
    DELETE(-1),
    /**
     * 禁用/过期/下架
     */
    DISABLE(0),
    /**
     * 启用/未过期/上架
     */
    ENABLE(1),
    /**
     * 违规下架/未启用
     */
    OFFLINE(2),
    /**
     * 等待审核
     */
    WAIT_AUDIT(3),
    /**
     * 关闭
     */
    FINISHED(4)
    ;
    private final Integer value;
    public Integer value() {
        return value;
    }
    StatusEnum(Integer value) {
        this.value = value;
    }
    public static StatusEnum instance(Integer value) {
        StatusEnum[] enums = values();
        for (StatusEnum statusEnum : enums) {
            if (statusEnum.value().equals(value)) {
                return statusEnum;
            }
        }
        return null;
    }
    public static Boolean offlineStatus (Integer value) {
        StatusEnum[] enums = values();
        for (StatusEnum statusEnum : enums) {
            if (statusEnum.value().equals(value)) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }
    public static Boolean offlineOrDelete (Integer status) {
        if (Objects.equals(status, OFFLINE.value) || Objects.equals(status, DELETE.value) || Objects.equals(status, DISABLE.value)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/enums/UserLevelType.java
New file
@@ -0,0 +1,44 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.enums;
/**
 * 会员等级类型
 *
 * @author yami
 */
public enum UserLevelType {
    /** 普通会员 */
    ORDINARY(0),
    /** vip会员 */
    VIP(1),
    ;
    private Integer num;
    public Integer value() {
        return num;
    }
    UserLevelType(Integer num){
        this.num = num;
    }
    public static UserLevelType instance(Integer value) {
        UserLevelType[] enums = values();
        for (UserLevelType statusEnum : enums) {
            if (statusEnum.value().equals(value)) {
                return statusEnum;
            }
        }
        return null;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/enums/WalletEnum.java
New file
@@ -0,0 +1,89 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.enums;
/**
 * 币种
 */
public enum WalletEnum {
    /**
     * 余额
     */
    BALANCE(3),
    /**
     * 瓜瓜豆
     */
    BEAN(4),
    /**
     * 绿积分
     */
    GREENPOINT(5),
    /**
     * 红积分
     */
    REDPOINT(6),
    /**
     * 蓝积分
     */
    BLUEPOINT(7),
    /**
     *流量
     */
    FLOW(8),
    /*
     * 金牛豆
     */
    GOLDCOWBEAN(9),
    /*
     * 幸运池
     */
    LUCKPOOL(10),
    /**
     * 积分
     */
    INTEGRAL(11),
    /*
     * 贡献值
     */
    CREDIT(12),
    /**
     * 合金豆
     */
    ALLOY(13),
    ;
    private final Integer value;
    public Integer value() {
        return value;
    }
    WalletEnum(Integer value) {
        this.value = value;
    }
    public static WalletEnum instance(Integer value) {
        WalletEnum[] enums = values();
        for (WalletEnum statusEnum : enums) {
            if (statusEnum.value().equals(value)) {
                return statusEnum;
            }
        }
        return null;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/exception/YamiShopBindException.java
New file
@@ -0,0 +1,75 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.exception;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.response.ResponseEnum;
import com.yami.shop.common.response.ServerResponseEntity;
import lombok.Data;
import lombok.Getter;
/**
 * 自定义异常
 * @author yami
 */
@Getter
public class YamiShopBindException extends RuntimeException{
    /**
     *
     */
    private static final long serialVersionUID = -4137688758944857209L;
    /**
     * http状态码
     */
    private String code;
    private Object object;
    private ServerResponseEntity<?> serverResponseEntity;
    /**
     * @param responseEnum http状态码
     */
    public YamiShopBindException(ResponseEnum responseEnum) {
        super(responseEnum.getMsg());
        this.code = responseEnum.value();
    }
    /**
     * @param responseEnum http状态码
     */
    public YamiShopBindException(ResponseEnum responseEnum, String msg) {
        super(I18nMessage.getMessage(msg));
        this.code = responseEnum.value();
    }
    public YamiShopBindException(ServerResponseEntity<?> serverResponseEntity) {
        this.serverResponseEntity = serverResponseEntity;
    }
    public YamiShopBindException(String msg) {
//        super(msg);
        super(I18nMessage.getMessage(msg));
        this.code = ResponseEnum.SHOW_FAIL.value();
    }
    public YamiShopBindException(String msg, Object object) {
        super(I18nMessage.getMessage(msg));
        this.code = ResponseEnum.SHOW_FAIL.value();
        this.object = object;
    }
    public YamiShopBindException(String code, String msg) {
        super(I18nMessage.getMessage(msg));
        this.code = code;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/filter/SensitiveFilter.java
New file
@@ -0,0 +1,112 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.filter;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import com.yami.shop.common.config.SensitiveWordConfig;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.handler.SensitiveHandler;
import com.yami.shop.common.wrapper.RequestWrapper;
import com.yami.shop.common.wrapper.ResponseWrapper;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
 * @author Citrus
 * @date 2021/8/17 11:05
 */
@Slf4j
@Component
public class SensitiveFilter implements Filter {
    Logger logger = LoggerFactory.getLogger(getClass().getName());
    @Autowired
    private SensitiveHandler sensitiveHandler;
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        ServletRequestAttributes attributes = new ServletRequestAttributes(req, resp);
        RequestContextHolder.setRequestAttributes(attributes);
        logger.info("uri:{}", req.getRequestURI());
        Set<String> sensitiveWhiteSet = SensitiveWordConfig.getSensitiveWhiteSet();
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        if (CollectionUtil.isNotEmpty(sensitiveWhiteSet)){
            for (String sensitiveUrl : sensitiveWhiteSet) {
                if (antPathMatcher.match(sensitiveUrl,req.getRequestURI())){
                    chain.doFilter(req, resp);
                    return;
                }
            }
        }
        ResponseWrapper responseWrapper = new ResponseWrapper(resp);
        // 敏感词输入过滤
        if (StrUtil.isNotBlank(req.getContentType()) && req.getContentType().contains(ContentType.JSON.getValue())) {
            RequestWrapper requestWrapper;
            requestWrapper = new RequestWrapper(req);
            String body = requestWrapper.getBody();
            if (StrUtil.isNotBlank(body) && sensitiveHandler.isSensitive(body)) {
                throw new YamiShopBindException("yami.sensitive.words.reenter");
            }
            chain.doFilter(requestWrapper, responseWrapper);
        } else {
            Map<String, String[]> parameterMap = req.getParameterMap();
            StringBuilder stringBuilder = new StringBuilder();
            for (String s : parameterMap.keySet()) {
                stringBuilder.append(parameterMap.get(s)[0]);
            }
            // 传入参数是否包含敏感词,最小匹配
            if (StrUtil.isNotBlank(stringBuilder.toString()) && sensitiveHandler.isSensitive(stringBuilder.toString())) {
                throw new YamiShopBindException("yami.sensitive.words.reenter");
            }
            //xss
            chain.doFilter(req, responseWrapper);
        }
        boolean isType = Objects.nonNull(responseWrapper.getContentType()) &&
                (responseWrapper.getContentType().contains(ContentType.JSON.getValue()) || responseWrapper.getContentType().contains(ContentType.TEXT_PLAIN.getValue()));
        if (isType) {
            byte[] content = responseWrapper.getContent();
            //敏感词输出过滤
            if (content.length > 0) {
                String s = new String(content, StandardCharsets.UTF_8);
                //属于json格式再处理
                String sensitiveText = null;
                try {
                    sensitiveText = sensitiveHandler.replaceSensitiveWord(s, "*");
                } catch (Exception e) {
                    log.error("替换敏感词失败:", e);
                }
                ServletOutputStream outputStream = resp.getOutputStream();
                outputStream.write(sensitiveText != null ? sensitiveText.getBytes(StandardCharsets.UTF_8) : new byte[0]);
                outputStream.flush();
            }
        }
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/handler/EnumTypeHandler.java
New file
@@ -0,0 +1,67 @@
package com.yami.shop.common.handler;
import com.yami.shop.common.enums.CodeBaseEnum;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
 * @auth lxw
 * @date 2024/4/25
 * @desc mapper里字段到枚举类的映射
 */
@NoArgsConstructor
@Slf4j
public  class EnumTypeHandler<E extends Enum<?> & CodeBaseEnum> extends BaseTypeHandler<CodeBaseEnum> {
    private Class<E> clazz;
    public EnumTypeHandler(Class<E> enumType) {
        if (enumType == null)
            throw new IllegalArgumentException("Type argument cannot be null");
        this.clazz = enumType;
    }
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, CodeBaseEnum parameter, JdbcType jdbcType)
            throws SQLException {
        ps.setInt(i, parameter.getValue());
    }
    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return this.codeOf(clazz, rs.getInt(columnName));
    }
    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return this.codeOf(clazz, rs.getInt(columnIndex));
    }
    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return this.codeOf(clazz, cs.getInt(columnIndex));
    }
    /**
     * @param enumClass
     * @param code
     * @param <E>
     * @return
     */
    public static <E extends Enum<?> & CodeBaseEnum> E codeOf(Class<E> enumClass, int code) {
        E[] enumConstants = enumClass.getEnumConstants();   // [OTHER, VALID, INVALID]
        for (E e : enumConstants) {
            if (e.getValue() == code)
                return e;
        }
        return null;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/handler/HttpHandler.java
New file
@@ -0,0 +1,88 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.handler;
import cn.hutool.core.util.CharsetUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ServerResponseEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Objects;
/**
 * @author FrozenWatermelon
 * @date 2020/7/16
 */
@Component
public class HttpHandler {
    private static final Logger logger = LoggerFactory.getLogger(HttpHandler.class);
    @Autowired
    private ObjectMapper objectMapper;
    public <T> void printServerResponseToWeb(ServerResponseEntity<T> serverResponseEntity) {
        if (serverResponseEntity == null) {
            logger.info("print obj is null");
            return;
        }
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        if (requestAttributes == null) {
            logger.error("requestAttributes is null, can not print to web");
            return;
        }
        HttpServletResponse response = requestAttributes.getResponse();
        if (response == null) {
            logger.error("httpServletResponse is null, can not print to web");
            return;
        }
        logger.error("response error: " + serverResponseEntity.getMsg());
        response.setCharacterEncoding(CharsetUtil.UTF_8);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        PrintWriter printWriter = null;
        try {
            printWriter = response.getWriter();
            printWriter.write(objectMapper.writeValueAsString(serverResponseEntity));
        }
        catch (IOException e) {
            throw new YamiShopBindException("io 异常", e);
        }
    }
    public <T> void printServerResponseToWeb(YamiShopBindException yamiShopBindException) {
        if (yamiShopBindException == null) {
            logger.info("print obj is null");
            return;
        }
        if (Objects.nonNull(yamiShopBindException.getServerResponseEntity())) {
            printServerResponseToWeb(yamiShopBindException.getServerResponseEntity());
            return;
        }
        ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
        serverResponseEntity.setCode(yamiShopBindException.getCode());
        serverResponseEntity.setMsg(yamiShopBindException.getMessage());
        printServerResponseToWeb(serverResponseEntity);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/handler/SensitiveHandler.java
New file
@@ -0,0 +1,259 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.handler;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONValidator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.yami.shop.common.bean.SensitiveWord;
import com.yami.shop.common.bean.event.GetSensitiveWordEvent;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.exception.YamiShopBindException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
 * @author FrozenWatermelon
 * @date 2021/12/29
 */
@Component
public class SensitiveHandler {
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private ObjectMapper objectMapper;
    /**
     * 缓存
     */
    private static final Cache<Object, Object> CONFIG_MAP = Caffeine.newBuilder()
            // 数量上限
            .maximumSize(1)
            // 过期机制
            .expireAfterWrite(5, TimeUnit.MINUTES).build();
    /**
     * 最小匹配
     */
    public static int minMatchType = 1;
    /**
     * 最大匹配
     */
    public static int maxMatchType = 2;
    private static final String IS_END = "isEnd";
    private static final String IS_ONE = "1";
    /**
     * 是否有敏感词
     * @param txt
     * @return
     */
    public boolean isSensitive(String txt) {
        return isSensitive(txt, minMatchType);
    }
    public boolean isSensitive(String txt, int matchType) {
        boolean flag = false;
        for (int i = 0; i < txt.length(); i++) {
            int matchFlag = this.checkSensitiveWord(txt, i, matchType);
            if (matchFlag > 0) {
                flag = true;
            }
        }
        return flag;
    }
    /**
     * 替换敏感词
     * @param txt
     * @param replaceChar
     * @return
     */
    public String replaceSensitiveWord(String txt, String replaceChar) {
        JSON json;
        if (JSONValidator.Type.Object.equals(JSONValidator.from(txt).getType())) {
            json = JSON.parseObject(txt);
        } else if (JSONValidator.Type.Array.equals(JSONValidator.from(txt).getType())) {
            json = JSON.parseArray(txt);
        }else {
            return replaceSensitiveWord(txt,maxMatchType, replaceChar);
        }
        jsonIterator(json, replaceChar);
        String jsonStr;
        try {
            jsonStr = objectMapper.writeValueAsString(json);
        } catch (IOException e) {
            throw new YamiShopBindException("io 异常");
        }
        return jsonStr;
    }
    public String replaceSensitiveWord(String txt, int matchType, String replaceChar) {
        String resultTxt = txt;
        Set<String> sensitiveWordSet = this.getSensitiveWord(txt, matchType);
        Iterator<String> iterator = sensitiveWordSet.iterator();
        String word;
        String replaceString;
        while (iterator.hasNext()) {
            word = iterator.next();
            replaceString = getReplaceChars(replaceChar, word.length());
            resultTxt = resultTxt.replaceAll(word, replaceString);
        }
        return resultTxt;
    }
    private void jsonIterator(JSON json, String replaceChar) {
        if (json instanceof JSONObject) {
            JSONObject jsonObject = (JSONObject)json;
            for (String key : jsonObject.keySet()) {
                Object object = jsonObject.get(key);
                if (Objects.nonNull(object)) {
                    String value = object.toString();
                    if (object instanceof JSON) {
                        jsonIterator((JSON)object, replaceChar);
                    } else if (object instanceof String){
                        jsonObject.put(key, replaceSensitiveWord(value, maxMatchType, replaceChar));
                    }
                }
            }
        } else if (json instanceof JSONArray){
            JSONArray jsonArray = (JSONArray)json;
            for (int key = 0; key < jsonArray.size(); key++) {
                Object object = jsonArray.get(key);
                if (object instanceof JSON) {
                    jsonIterator((JSON)object, replaceChar);
                } else if (object instanceof String){
                    jsonArray.set(key, replaceSensitiveWord(object.toString(), maxMatchType, replaceChar));
                }
            }
        }
    }
    public Set<String> getSensitiveWord(String txt, int matchType) {
        Set<String> sensitiveWordList = new HashSet<>();
        for (int i = 0; i < txt.length(); i++) {
            int length = checkSensitiveWord(txt, i, matchType);
            if (length > 0) {
                sensitiveWordList.add(txt.substring(i, i + length));
                i = i + length - 1;
            }
        }
        return sensitiveWordList;
    }
    private String getReplaceChars(String replaceChar, int length) {
        StringBuilder resultReplace = new StringBuilder();
        resultReplace.append(replaceChar);
        for (int i = 1; i < length; i++) {
            resultReplace.append(replaceChar);
        }
        return resultReplace.toString();
    }
    private int checkSensitiveWord(String txt, int beginIndex, int matchType) {
        Map nowMap = getSensitiveWordMap();
        boolean flag = false;
        char word = 0;
        int matchFlag = 0;
        for (int i = beginIndex; i < txt.length(); i++) {
            word = txt.charAt(i);
            nowMap = (Map) nowMap.get(word);
            if (Objects.isNull(nowMap)) {
                break;
            }
            matchFlag++;
            if (isEnd(nowMap)) {
                flag = true;
                if (Objects.equals(minMatchType, matchType)) {
                    break;
                }
            }
        }
        if (matchFlag <= 1 || !flag) {
            matchFlag = 0;
        }
        return matchFlag;
    }
    private boolean isEnd(Map nowMap) {
        boolean flag = false;
        if (Objects.equals(nowMap.get(IS_END), IS_ONE)) {
            flag = true;
        }
        return flag;
    }
    private Map getSensitiveWordMap() {
        Map finalMap = (Map) CONFIG_MAP.get(Constant.SENSITIVE_WORDS, cacheKey -> {
            SensitiveWord sensitiveWord = new SensitiveWord();
            try {
                applicationContext.publishEvent(new GetSensitiveWordEvent(Constant.SENSITIVE_WORDS,sensitiveWord));
            } catch (Exception e) {
                return Collections.emptyMap();
            }
            if (StrUtil.isBlank(sensitiveWord.getSensitiveWord())) {
                return Collections.emptyMap();
            }
            //根据中文逗号分隔
            List<String> sensitiveWordsList = Arrays.asList(sensitiveWord.getSensitiveWord().split(Constant.CN_COMMA));
            HashSet<String> sensitiveWordSet = new HashSet<>(sensitiveWordsList);
            Iterator<String> iterator = sensitiveWordSet.iterator();
            String key;
            Map nowMap;
            Map<String, String> newWordMap;
            Map<Object, Object> sensitiveWordMap = new HashMap<>(sensitiveWordSet.size());
            while (iterator.hasNext()) {
                //敏感词
                key = iterator.next();
                nowMap = sensitiveWordMap;
                for (int i = 0; i < key.length(); i++) {
                    //敏
                    char charAt = key.charAt(i);
                    Object wordMap = nowMap.get(charAt);
                    if (wordMap != null) {
                        //逐字加入map
                        nowMap = (Map) wordMap;
                    } else {
                        newWordMap = new HashMap<>(sensitiveWordSet.size());
                        //最后一个字,加标记
                        newWordMap.put("isEnd", "0");
                        nowMap.put(charAt, newWordMap);
                        nowMap = newWordMap;
                    }
                    if (i == key.length() - 1) {
                        //结束
                        nowMap.put("isEnd", "1");
                    }
                }
            }
            return sensitiveWordMap;
        });
        if (finalMap == null) {
            CONFIG_MAP.invalidate(Constant.SENSITIVE_WORDS);
        }
        return finalMap;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/i18n/I18nMessage.java
New file
@@ -0,0 +1,144 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.i18n;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import java.io.IOException;
import java.util.Locale;
import java.util.Objects;
/**
 * 多语言国际化消息工具类
 * @author yami
 */
@Slf4j
public class I18nMessage {
    private static MessageSourceAccessor accessor;
//    private static final String BASE_FOLDE = "i18n";
    private static final String BASE_NAME = "i18n/messages";
    static{
        ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource = new ReloadableResourceBundleMessageSource();
        reloadableResourceBundleMessageSource.setBasenames(BASE_NAME);
        reloadableResourceBundleMessageSource.setCacheSeconds(5);
        reloadableResourceBundleMessageSource.setDefaultEncoding("UTF-8");
        accessor = new MessageSourceAccessor(reloadableResourceBundleMessageSource);
    }
//    /**
//     * 获取一条语言配置信息
//     *
//     * @param message 配置信息属性名,eg: api.response.code.user.signUp
//     * @return
//     */
//    public static String getMessage(String message) {
//        Locale locale = LocaleContextHolder.getLocale();
//        return I18nMessage.accessor.getMessage(message,locale);
//    }
    /**
     * 获取一条语言配置信息
     *
     * @param message 配置信息属性名,eg: api.response.code.user.signUp
     * @return
     */
    public static String getMessage(String message) {
        Locale locale = LocaleContextHolder.getLocale();
        try {
            return accessor.getMessage(message,locale);
        }catch (Exception e){
            return message;
        }
    }
    /**
     * 获取一条语言配置信息(后台管理)
     *
     * @return
     * @throws IOException
     */
    public static Integer getLang() {
        Locale locale = LocaleContextHolder.getLocale();
        return LanguageEnum.valueOf(locale).getLang();
    }
    /**
     * 获取一条语言配置信息(小程序、pc)
     *
     * @return
     * @throws IOException
     */
    public static Integer getDbLang() {
        Integer lang = getLang();
        if (Objects.equals(lang, 0)) {
            return LanguageEnum.LANGUAGE_ZH_CN.getLang();
        }
        return lang;
    }
//    /**
//     * 获取文件夹下所有的国际化文件名
//     *
//     * @param folderName 文件名
//     * @return
//     * @throws IOException
//     */
//    private static String[] getAllBaseNames(final String folderName) throws IOException {
//        URL url = Thread.currentThread().getContextClassLoader()
//                .getResource(folderName);
//        if (null == url) {
//            throw new RuntimeException("无法获取资源文件路径");
//        }
//
//        List<String> baseNames = new ArrayList<>();
//        if (url.getProtocol().equalsIgnoreCase("file")) {
//            // 文件夹形式,用File获取资源路径
//            File file = new File(url.getFile());
//            if (file.exists() && file.isDirectory()) {
//                baseNames = Files.walk(file.toPath())
//                        .filter(path -> path.toFile().isFile())
//                        .map(Path::toString)
//                        .map(path -> path.substring(path.indexOf(folderName)))
//                        .map(I18nMessage::getI18FileName)
//                        .distinct()
//                        .collect(Collectors.toList());
//            } else {
//                log.error("指定的baseFile不存在或者不是文件夹");
//            }
//        }
//        return baseNames.toArray(new String[0]);
//    }
//
//    /**
//     * 把普通文件名转换成国际化文件名
//     *
//     * @param filename
//     * @return
//     */
//    private static String getI18FileName(String filename) {
//        filename = filename.replace(".properties", "");
////        for (int i = 0; i < 2; i++) {
////            int index = filename.lastIndexOf("_");
////            if (index != -1) {
////                filename = filename.substring(0, index);
////            }
////        }
//        return filename.replace("\\", "/");
//    }
}
yami-shop-common/src/main/java/com/yami/shop/common/i18n/LanguageEnum.java
New file
@@ -0,0 +1,82 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.i18n;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import java.util.Locale;
import java.util.Objects;
/**
 * 国际化 语言枚举类
 * @author LGH
 */
@Getter
@AllArgsConstructor
public enum LanguageEnum {
    /**
     * 简体中文
     */
    LANGUAGE_ZH_CN("zh", 0),
    /**
     * 英文
     */
    LANGUAGE_EN("en", 1)
    ;
    private String language;
    private Integer lang;
    /**
     * 获取指定语言类型(如果没有对应的语言类型,则返回中文)
     *
     * @param language 语言类型
     * @return
     */
    public static String getLanguageType(String language){
        if (StrUtil.isEmpty(language)) {
            return LANGUAGE_ZH_CN.language;
        }
        for (LanguageEnum languageEnum : LanguageEnum.values()) {
            if (languageEnum.language.equalsIgnoreCase(language)) {
                return languageEnum.language;
            }
        }
        return LANGUAGE_ZH_CN.language;
    }
    public static LanguageEnum valueOf(int lang) {
        for (LanguageEnum languageEnum : values()) {
            if (languageEnum.lang == lang) {
                return languageEnum;
            }
        }
        return LanguageEnum.LANGUAGE_ZH_CN;
    }
    public static LanguageEnum valueOf(Locale locale) {
        for (LanguageEnum languageEnum : values()) {
            if (Objects.equals(languageEnum.language, locale.toString())) {
                return languageEnum;
            }
        }
        return LanguageEnum.LANGUAGE_ZH_CN;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/i18n/YamiLocaleChangeFilter.java
New file
@@ -0,0 +1,52 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.i18n;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Locale;
import java.util.Objects;
/**
 * RequestContextFilter 会传入默认的Locale,优先级(-105) 要比RequestContextFilter优先级高
 * @author LGH
 */
@Slf4j
@Component
@Order(-104)
public class YamiLocaleChangeFilter implements Filter {
    public static String ZH_CN = "zh_CN";
    public static String ZH_CN_L = "zh_cn";
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String newLocale = request.getHeader("locale");
        if(Objects.equals(newLocale,"zh_CN")||Objects.equals(newLocale,"zh_cn")){
            newLocale = "zh";
        }
        if (newLocale != null) {
            String lowerLocale = newLocale.toLowerCase();
            LocaleContextHolder.setLocale(new Locale(lowerLocale));
        }
        filterChain.doFilter(request, response);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/i18n/YamiLocaleChangeInterceptor.java
New file
@@ -0,0 +1,57 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.i18n;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.support.RequestContextUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @author LGH
 */
@Component("localeChangeInterceptor")
@Slf4j
public class YamiLocaleChangeInterceptor extends LocaleChangeInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String newLocale = request.getHeader(getParamName());
        if (newLocale != null) {
                LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
                if (localeResolver == null) {
                    throw new IllegalStateException(
                            "No LocaleResolver found: not in a DispatcherServlet request?");
                }
                try {
                    localeResolver.setLocale(request, response, parseLocaleValue(newLocale));
                }
                catch (IllegalArgumentException ex) {
                    if (isIgnoreInvalidLocale()) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Ignoring invalid locale value [" + newLocale + "]: " + ex.getMessage());
                        }
                    }
                    else {
                        throw ex;
                    }
                }
        }
        // Proceed in any case.
        return true;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/response/R.java
New file
@@ -0,0 +1,214 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.response;
import io.swagger.v3.oas.annotations.media.Schema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.Objects;
/**
 * 响应实体
 * @author yami
 */
public class R<T> implements Serializable {
    private static final Logger log = LoggerFactory.getLogger(R.class);
    /**
     * 状态码
     */
    @Schema(description = "状态码" )
    private String code;
    /**
     * 信息
     */
    @Schema(description = "信息" )
    private String msg;
    /**
     * 数据
     */
    @Schema(description = "数据" )
    private T data;
    /**
     * 版本
     */
    private String version;
    /**
     * 时间
     */
    private Long timestamp;
    private String sign;
    public String getSign() {
        return sign;
    }
    public void setSign(String sign) {
        this.sign = sign;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public T getData() {
        return data;
    }
    public R setData(T data) {
        this.data = data;
        return this;
    }
    public Long getTimestamp() {
        return timestamp;
    }
    public void setTimestamp(Long timestamp) {
        this.timestamp = timestamp;
    }
    public String getVersion() {
        return version;
    }
    public void setVersion(String version) {
        this.version = version;
    }
    public boolean isSuccess() {
        return Objects.equals(ResponseEnum.OK.value(), this.code);
    }
    public boolean isFail() {
        return !Objects.equals(ResponseEnum.OK.value(), this.code);
    }
    public R() {
        // 版本号
        this.version = "mall4j.v230213";
    }
    public static <T> R<T> success(T data) {
        R<T> serverResponseEntity = new R<>();
        serverResponseEntity.setData(data);
        serverResponseEntity.setCode(ResponseEnum.OK.value());
        return serverResponseEntity;
    }
    public static <T> R<T> success() {
        R<T> serverResponseEntity = new R<>();
        serverResponseEntity.setCode(ResponseEnum.OK.value());
        serverResponseEntity.setMsg(ResponseEnum.OK.getMsg());
        return serverResponseEntity;
    }
    public static <T> R<T> success(Integer code, T data) {
        return success(String.valueOf(code), data);
    }
    public static <T> R<T> success(String code, T data) {
        R<T> serverResponseEntity = new R<>();
        serverResponseEntity.setCode(code);
        serverResponseEntity.setData(data);
        return serverResponseEntity;
    }
    /**
     * 前端显示失败消息
     * @param msg 失败消息
     * @return
     */
    public static <T> R<T> showFailMsg(String msg) {
        log.error(msg);
        R<T> serverResponseEntity = new R<>();
        serverResponseEntity.setMsg(msg);
        serverResponseEntity.setCode(ResponseEnum.SHOW_FAIL.value());
        return serverResponseEntity;
    }
    public static <T> R<T> fail(ResponseEnum responseEnum) {
        log.error(responseEnum.toString());
        R<T> serverResponseEntity = new R<>();
        serverResponseEntity.setMsg(responseEnum.getMsg());
        serverResponseEntity.setCode(responseEnum.value());
        return serverResponseEntity;
    }
    public static <T> R<T> fail(ResponseEnum responseEnum, T data) {
        log.error(responseEnum.toString());
        R<T> serverResponseEntity = new R<>();
        serverResponseEntity.setMsg(responseEnum.getMsg());
        serverResponseEntity.setCode(responseEnum.value());
        serverResponseEntity.setData(data);
        return serverResponseEntity;
    }
    public static <T> R<T> fail(String code, String msg, T data) {
        log.error(msg);
        R<T> serverResponseEntity = new R<>();
        serverResponseEntity.setMsg(msg);
        serverResponseEntity.setCode(code);
        serverResponseEntity.setData(data);
        return serverResponseEntity;
    }
    public static <T> R<T> fail(String code, String msg) {
        return fail(code, msg, null);
    }
    public static <T> R<T> fail(Integer code, T data) {
        R<T> serverResponseEntity = new R<>();
        serverResponseEntity.setCode(String.valueOf(code));
        serverResponseEntity.setData(data);
        return serverResponseEntity;
    }
    @SuppressWarnings("unchecked")
    public static <T> R<T> transform(R<?> oldServerResponseEntity) {
        R<T> serverResponseEntity = new R<>();
        serverResponseEntity.setMsg(oldServerResponseEntity.getMsg());
        serverResponseEntity.setCode(oldServerResponseEntity.getCode());
        serverResponseEntity.setData((T) oldServerResponseEntity.getData());
        log.error(serverResponseEntity.toString());
        return serverResponseEntity;
    }
    @Override
    public String toString() {
        return "ServerResponseEntity{" +
                "code='" + code + '\'' +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                ", version='" + version + '\'' +
                ", timestamp=" + timestamp +
                ", sign='" + sign + '\'' +
                '}';
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/response/ResponseCode.java
New file
@@ -0,0 +1,22 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.response;
/**
 * 响应码
 * @author yami
 */
public interface ResponseCode {
    int SUCCESS = 1;
    int WX_SUCCESS = 0;
    int FAIL = -1;
}
yami-shop-common/src/main/java/com/yami/shop/common/response/ResponseEnum.java
New file
@@ -0,0 +1,174 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.response;
/**
 * @author FrozenWatermelon
 * @date 2020/7/9
 */
public enum ResponseEnum {
    /**
     * ok
     */
    OK("00000", "ok"),
    /**
     * ok
     */
    ERROR("99999", "失败"),
    /**
     * 用于直接显示提示用户的错误,内容由输入内容决定
     */
    SHOW_FAIL("A00001", ""),
    /**
     * 用于直接显示提示系统的成功,内容由输入内容决定
     */
    SHOW_SUCCESS("A00002", ""),
    /**
     * 未授权
     */
    UNAUTHORIZED("A00004", "Unauthorized"),
    /**
     * 服务器出了点小差
     */
    EXCEPTION("A00005", "服务器出了点小差"),
//
//    /**
//     * 验证码有误
//     */
//    VERIFICATION_CODE_ERROR("A00006", "验证码有误或已过期"),
//
//    /**
//     * 数据异常
//     */
//    DATA_ERROR("A00007", "数据异常,请刷新后重新操作"),
//
//    /**
//     * 一些需要登录的接口,而实际上因为前端无法知道token是否已过期,导致token已失效时,
//     * 应该返回一个状态码,告诉前端token已经失效了,及时清理
//     */
//    CLEAN_TOKEN("A00008", "clean token"),
//
//    /**
//     * 刷新token已过期
//     */
//    REFRESH_TOKEN_EXIST("A00009", "refresh token exist"),
//
//    /**
//     * 数据不完整
//     */
//    DATA_INCOMPLETE("A00010", "数据不完整"),
//
//    /**
//     * 有敏感词
//     */
//    SENSITIVE_WORD("A00011","存在敏感词,请重新输入"),
    /**
     * TempUid异常
     * 一般不会出现这个异常,出现这个异常会有两种已知可能
     * 1. 一种是旧的tempUid
     * 2. 一种是同域名的localstorage 有个也叫tempUid的存储覆盖了(有的人测试环境和正式环境放在同一个域名不同子目录下)
     * 如果前端看到返回了这个异常,为了让用户能够顺利登录,需要重新获取一遍code,重新获取tempUid
     */
    TEMP_UID_ERROR("A00012", "TempUid Error"),
    /**
     * 接口不存在
     */
    NOT_FOUND("A00013", "接口不存在"),
    /**
     * 方法参数没有校验,内容由输入内容决定
     */
    METHOD_ARGUMENT_NOT_VALID("A00014", "方法参数没有校验"),
    /**
     * 01开头代表商品
     * 商品已下架,返回特殊的状态码,用于渲染商品下架的页面
     */
//    SPU_NOT_EXIST("A01000", "商品不存在"),
    /**
     * 02开头代表购物车
     */
//    SHOP_CART_NOT_EXIST("A02000", "商品已下架"),
    /**
     * 03开头代表订单
     */
//    ORDER_NOT_EXIST("A03000", "订单不存在"),
    /**
     * 订单不支持该配送方式
     */
    ORDER_DELIVERY_NOT_SUPPORTED("A03001", "The delivery method is not supported"),
    /**
     * 请勿重复提交订单,
     * 1.当前端遇到该异常时,说明前端防多次点击没做好
     * 2.提示用户 订单已发生改变,请勿重复下单
     */
    REPEAT_ORDER("A03002", "订单已过期,请重新下单"),
    /**
     * 优惠券不能共用
     */
    COUPON_CANNOT_USE_TOGETHER("A03003", "优惠券不能共用"),
    /**
     * 库存不足,body会具体返回那个skuid的库存不足,后台通过skuId知道哪个商品库存不足,前端不需要判断
     */
    NOT_STOCK("A03010", "not stock"),
    /**
     * 该社交账号被其他用户绑定了,如果返回这个状态码,前端应该提示用户解绑已经绑定的账号重新绑定
     */
    SOCIAL_ACCOUNT_BIND_BY_OTHER("A04002", "social account bind by other"),
    /**
     * 该社交账号被其他用户绑定了,如果返回这个状态码,前端应该提示用户解绑已经绑定的账号重新绑定
     */
    TAOBAO_OAUTH_FAIL("A05001", "oauth fail"),
    /**
     * 用户收货地址超过配送范围
     */
    DELIVERY_OVER("A07001", "")
    ;
    private final String code;
    private final String msg;
    public String value() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
    ResponseEnum(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    @Override
    public String toString() {
        return "ResponseEnum{" + "code='" + code + '\'' + ", msg='" + msg + '\'' + "} " + super.toString();
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/response/ServerResponseEntity.java
New file
@@ -0,0 +1,214 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.response;
import io.swagger.v3.oas.annotations.media.Schema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.Objects;
/**
 * 响应实体
 * @author yami
 */
public class ServerResponseEntity<T> implements Serializable {
    private static final Logger log = LoggerFactory.getLogger(ServerResponseEntity.class);
    /**
     * 状态码
     */
    @Schema(description = "状态码" )
    private String code;
    /**
     * 信息
     */
    @Schema(description = "信息" )
    private String msg;
    /**
     * 数据
     */
    @Schema(description = "数据" )
    private T data;
    /**
     * 版本
     */
    private String version;
    /**
     * 时间
     */
    private Long timestamp;
    private String sign;
    public String getSign() {
        return sign;
    }
    public void setSign(String sign) {
        this.sign = sign;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public T getData() {
        return data;
    }
    public ServerResponseEntity setData(T data) {
        this.data = data;
        return this;
    }
    public Long getTimestamp() {
        return timestamp;
    }
    public void setTimestamp(Long timestamp) {
        this.timestamp = timestamp;
    }
    public String getVersion() {
        return version;
    }
    public void setVersion(String version) {
        this.version = version;
    }
    public boolean isSuccess() {
        return Objects.equals(ResponseEnum.OK.value(), this.code);
    }
    public boolean isFail() {
        return !Objects.equals(ResponseEnum.OK.value(), this.code);
    }
    public ServerResponseEntity() {
        // 版本号
        this.version = "mall4j.v230213";
    }
    public static <T> ServerResponseEntity<T> success(T data) {
        ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
        serverResponseEntity.setData(data);
        serverResponseEntity.setCode(ResponseEnum.OK.value());
        return serverResponseEntity;
    }
    public static <T> ServerResponseEntity<T> success() {
        ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
        serverResponseEntity.setCode(ResponseEnum.OK.value());
        serverResponseEntity.setMsg(ResponseEnum.OK.getMsg());
        return serverResponseEntity;
    }
    public static <T> ServerResponseEntity<T> success(Integer code, T data) {
        return success(String.valueOf(code), data);
    }
    public static <T> ServerResponseEntity<T> success(String code, T data) {
        ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
        serverResponseEntity.setCode(code);
        serverResponseEntity.setData(data);
        return serverResponseEntity;
    }
    /**
     * 前端显示失败消息
     * @param msg 失败消息
     * @return
     */
    public static <T> ServerResponseEntity<T> showFailMsg(String msg) {
        log.error(msg);
        ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
        serverResponseEntity.setMsg(msg);
        serverResponseEntity.setCode(ResponseEnum.SHOW_FAIL.value());
        return serverResponseEntity;
    }
    public static <T> ServerResponseEntity<T> fail(ResponseEnum responseEnum) {
        log.error(responseEnum.toString());
        ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
        serverResponseEntity.setMsg(responseEnum.getMsg());
        serverResponseEntity.setCode(responseEnum.value());
        return serverResponseEntity;
    }
    public static <T> ServerResponseEntity<T> fail(ResponseEnum responseEnum, T data) {
        log.error(responseEnum.toString());
        ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
        serverResponseEntity.setMsg(responseEnum.getMsg());
        serverResponseEntity.setCode(responseEnum.value());
        serverResponseEntity.setData(data);
        return serverResponseEntity;
    }
    public static <T> ServerResponseEntity<T> fail(String code, String msg, T data) {
        log.error(msg);
        ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
        serverResponseEntity.setMsg(msg);
        serverResponseEntity.setCode(code);
        serverResponseEntity.setData(data);
        return serverResponseEntity;
    }
    public static <T> ServerResponseEntity<T> fail(String code, String msg) {
        return fail(code, msg, null);
    }
    public static <T> ServerResponseEntity<T> fail(Integer code, T data) {
        ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
        serverResponseEntity.setCode(String.valueOf(code));
        serverResponseEntity.setData(data);
        return serverResponseEntity;
    }
    @SuppressWarnings("unchecked")
    public static <T> ServerResponseEntity<T> transform(ServerResponseEntity<?> oldServerResponseEntity) {
        ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
        serverResponseEntity.setMsg(oldServerResponseEntity.getMsg());
        serverResponseEntity.setCode(oldServerResponseEntity.getCode());
        serverResponseEntity.setData((T) oldServerResponseEntity.getData());
        log.error(serverResponseEntity.toString());
        return serverResponseEntity;
    }
    @Override
    public String toString() {
        return "ServerResponseEntity{" +
                "code='" + code + '\'' +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                ", version='" + version + '\'' +
                ", timestamp=" + timestamp +
                ", sign='" + sign + '\'' +
                '}';
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/response/WxLiveProdResponse.java
New file
@@ -0,0 +1,40 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.response;
import lombok.Data;
import java.io.Serializable;
import java.util.Objects;
/**
 * 微信直播商品响应参数
 * @author yami
 */
@Data
public class WxLiveProdResponse<T> implements Serializable {
    private int errcode;
    private Integer total;
    private String msg;
    private T goods;
    private Long roomId;
    public boolean isSuccess(){
        return Objects.equals(ResponseCode.WX_SUCCESS, this.errcode);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/response/WxServerResponse.java
New file
@@ -0,0 +1,50 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.response;
import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder;
import com.google.gson.annotations.SerializedName;
import com.yami.shop.common.wx.bean.resp.LiveUserRespInfo;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
/**
 * 微信响应参数
 * @author yami
 */
@Data
public class WxServerResponse<T> implements Serializable {
    private int errcode;
    private Integer total;
    private String msg;
    @SerializedName("list")
    private List<LiveUserRespInfo> list;
    private T roomInfo;
    private Long roomId;
    public boolean isSuccess(){
        return Objects.equals(ResponseCode.WX_SUCCESS, this.errcode);
    }
    public static WxServerResponse fromJson(String json) {
        return WxMaGsonBuilder.create().fromJson(json, WxServerResponse.class);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/serializer/json/ImgJsonSerializer.java
New file
@@ -0,0 +1,73 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.serializer.json;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.yami.shop.common.bean.Domain;
import com.yami.shop.common.bean.SysConfig;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.util.CacheManagerUtil;
import com.yami.shop.common.util.Json;
import com.yami.shop.common.util.SpringContextUtils;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * 图片加上前缀
 * @author yami
 */
@Component
public class ImgJsonSerializer extends JsonSerializer<String> {
    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        CacheManagerUtil cacheManagerUtil = SpringContextUtils.getBean(CacheManagerUtil.class);
        if (StrUtil.isBlank(value)) {
            gen.writeString(StrUtil.EMPTY);
            return;
        }
        String[] imgs = value.split(StrUtil.COMMA);
        StringBuilder sb = new StringBuilder();
        if (ArrayUtil.isEmpty(imgs)) {
            gen.writeString(sb.toString());
            return;
        }
        String rule="^((http[s]{0,1})://)";
        Pattern pattern= Pattern.compile(rule);
        Domain domain = cacheManagerUtil.getCache("SysConfigObject", Constant.DOMAIN_CONFIG);
        if (domain == null) {
            SysConfig config = SpringContextUtils.getBean(SqlSession.class).selectOne("com.yami.shop.dao.SysConfigMapper.queryByKey", Constant.DOMAIN_CONFIG);
            domain = Json.parseObject(config.getParamValue(),Domain.class);
            cacheManagerUtil.putCache("SysConfigObject", Constant.DOMAIN_CONFIG, domain);
        }
        for (String img : imgs) {
            Matcher matcher=pattern.matcher(img);
            //若图片以http或https开头,直接返回
            if (matcher.find()){
                sb.append(img).append(StrUtil.COMMA);
            }else {
                sb.append(domain.getResourcesDomainName()).append("/").append(img).append(StrUtil.COMMA);
            }
        }
        sb.deleteCharAt(sb.length()-1);
        gen.writeString(sb.toString());
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/Arith.java
New file
@@ -0,0 +1,211 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;
/**
 * 算术工具类
 * @author yami
 */
public class Arith {
    /**
     * 默认除法运算精度
     */
    private static final int DEF_DIV_SCALE = 10;
    /**
     * 这个类不能实例化
     */
    private Arith() {
    }
    /**
     * 提供精确的加法运算。.
     *
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static double add(double v1, double v2) {
        String s1 = Double.toString(v1);
        String s2 = Double.toString(v2);
        // 必须转换成String
        BigDecimal b1 = new BigDecimal(s1);
        BigDecimal b2 = new BigDecimal(s2);
        return b1.add(b2).doubleValue();
    }
    /**
     * 提供精确的加法运算。.
     *
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static double addMayBeEmpty(Double v1, Double v2) {
        if(Objects.isNull(v1)){
            v1 = 0.0;
        }
        if(Objects.isNull(v2)){
            v2 = 0.0;
        }
        String s1 = Double.toString(v1);
        String s2 = Double.toString(v2);
        // 必须转换成String
        BigDecimal b1 = new BigDecimal(s1);
        BigDecimal b2 = new BigDecimal(s2);
        return b1.add(b2).doubleValue();
    }
    /**
     * 提供精确的减法运算。.
     *
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static double sub(double v1, double v2) {
        String s1 = Double.toString(v1);
        String s2 = Double.toString(v2);
        // 必须转换成String
        BigDecimal b1 = new BigDecimal(s1);
        BigDecimal b2 = new BigDecimal(s2);
        return b1.subtract(b2).doubleValue();
    }
    /**
     * 提供精确的乘法运算。.
     *
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static double mul(double v1, double v2) {
        String s1 = Double.toString(v1);
        String s2 = Double.toString(v2);
        // 必须转换成String
        BigDecimal b1 = new BigDecimal(s1);
        BigDecimal b2 = new BigDecimal(s2);
        return b1.multiply(b2).doubleValue();
    }
    /**
     * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。.
     *
     * @param v1 被除数
     * @param v2 除数
     * @return 两个参数的商
     */
    public static double div(double v1, double v2) {
        if (v2 == 0){
            return 0.0;
        }
        return div(v1, v2, DEF_DIV_SCALE);
    }
    /**
     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指定精度,以后的数字采用银行家舍入
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static double div(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        if (v2 == 0){
            return 0.0;
        }
        String s1 = Double.toString(v1);
        String s2 = Double.toString(v2);
        // 必须转换成String
        BigDecimal b1 = new BigDecimal(s1);
        BigDecimal b2 = new BigDecimal(s2);
        return b1.divide(b2, scale, RoundingMode.HALF_EVEN).doubleValue();
    }
    /**
     * 提供精确的小数位银行家舍入法
     *
     * @param v     需要处理的数字
     * @param scale 小数点后保留几位
     * @return 结果
     */
    public static double roundByBanker(double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        String s = Double.toString(v);
        BigDecimal b = new BigDecimal(s);
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, RoundingMode.HALF_EVEN).doubleValue();
    }
    /**
     * @param bigDecimal
     * @param bigDecimal2
     * @param bigDecimal3
     * @return
     */
    public static double add(BigDecimal bigDecimal, BigDecimal bigDecimal2, BigDecimal bigDecimal3) {
        return bigDecimal.add(bigDecimal2).add(bigDecimal3).doubleValue();
    }
    /**
     * @param preDepositPrice
     * @param finalPrice
     * @return
     */
    public static double add(BigDecimal preDepositPrice, BigDecimal finalPrice) {
        return preDepositPrice.add(finalPrice).doubleValue();
    }
    /**
     * 两个浮点数比较是否相等
     * @param v1
     * @param v2
     * @return
     */
    public static boolean isEquals(double v1, double v2) {
        String s1 = Double.toString(v1);
        String s2 = Double.toString(v2);
        // 必须转换成String
        BigDecimal b1 = new BigDecimal(s1);
        BigDecimal b2 = new BigDecimal(s2);
        return Objects.equals(b1,b2);
    }
    /**
     * 计算百分比
     * @param a 被除数
     * @param b 除数
     * @param scale 保留小数位
     * @param percentage 放大倍数
     * @return 放大倍数后的数值
     */
    public static BigDecimal calculatePercentage(Integer a, Integer b, int scale, Integer percentage) {
        boolean isCalculate = Objects.isNull(a) || Objects.isNull(b) || Objects.isNull(percentage) ||
                a.compareTo(0)==0 || b<0 || percentage.compareTo(0)==0 ;
        if (isCalculate) {
            return new BigDecimal("0");
        }
        BigDecimal bigDecimal = new BigDecimal(a.toString());
        BigDecimal divisor = new BigDecimal(b.toString());
        BigDecimal multiplicand = new BigDecimal(percentage.toString());
        return bigDecimal.multiply(multiplicand).divide(divisor,scale, RoundingMode.HALF_EVEN);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/BmapPoint.java
New file
@@ -0,0 +1,58 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
/**
 * 用于构造百度地图中的经纬度点
 *
 * @author zhengtian
 * @date 2013-8-5 下午02:54:41
 */
public class BmapPoint {
    /** 经度 */
    private double lng;
    /** 纬度 */
    private double lat;
    public BmapPoint() {
    }
    public BmapPoint(double lng, double lat) {
        this.lng = lng;
        this.lat = lat;
    }
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof BmapPoint) {
            BmapPoint bmapPoint = (BmapPoint) obj;
            return (bmapPoint.getLng() == lng && bmapPoint.getLat() == lat) ? true : false;
        } else {
            return false;
        }
    }
    public double getLng() {
        return lng;
    }
    public void setLng(double lng) {
        this.lng = lng;
    }
    public double getLat() {
        return lat;
    }
    public void setLat(double lat) {
        this.lat = lat;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/CacheManagerUtil.java
New file
@@ -0,0 +1,53 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import lombok.AllArgsConstructor;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;
/**
 * 缓存工具类
 * @author yami
 */
@Component
@AllArgsConstructor
public class CacheManagerUtil {
    private CacheManager cacheManager;
    @SuppressWarnings({"unchecked"})
    public <T> T getCache(String cacheName,String key) {
        Cache cache = cacheManager.getCache(cacheName);
        if (cache == null) {
            return null;
        }
        Cache.ValueWrapper valueWrapper = cache.get(key);
        if (valueWrapper == null) {
            return null;
        }
        return (T)valueWrapper.get();
    }
    public void putCache(String cacheName,String key, Object value) {
        Cache cache = cacheManager.getCache(cacheName);
        if (cache != null) {
            cache.put(key, value);
        }
    }
    public void evictCache(String cacheName,String key) {
        Cache cache = cacheManager.getCache(cacheName);
        if (cache != null) {
            cache.evict(key);
        }
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/CharUtil.java
New file
@@ -0,0 +1,38 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
/**
 * 获取带有中文字符的长度
 * @author yami
 */
public class CharUtil {
    /**
     * 得到一个字符串的长度,显示的长度,一个汉字或日韩文长度为2,英文字符长度为1
     * @param s 需要得到长度的字符串
     * @return int 得到的字符串长度
     */
    public static int length(String s) {
        if (s == null) {
            return 0;
        }
        int len = 0;
        for (char item : s.toCharArray()) {
            len++;
            if (item / 0x80 == 0) {
                continue;
            }
            len++;
        }
        return len;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/DateParam.java
New file
@@ -0,0 +1,26 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import lombok.Data;
import java.util.Date;
/**
 * 时间参数
 * @author yami
 */
@Data
public class DateParam {
    private Date startTime;
    private Date endTime;
}
yami-shop-common/src/main/java/com/yami/shop/common/util/DateUtils.java
New file
@@ -0,0 +1,444 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.yami.shop.common.bean.DateVO;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
/**
 * 时间工具类
 * @author yami
 */
public class DateUtils {
    public static final String yyyy = "yyyy";
    public static final String MM = "MM";
    public static final String dd = "dd";
    public static final String yyyyMMdd = "yyyyMMdd";
    public static final String yyyy_MM_dd = "yyyy-MM-dd";
    public static final String yyyy_MM_ddHHmmSS = "yyyy-MM-dd HH:mm:ss";
    public static String formatDate(String format){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(new Date());
    }
    public static Long dateToNumber(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String format = sdf.format(date);
        Long value = 0L;
        try {
            value = Long.valueOf(format);
        } catch (Exception e) {
            return value;
        }
        return value;
    }
    public static String dateToStrYmd(Date date) {
        String format = "yyyy-MM-dd";
        return DateUtil.format(date,format);
    }
    public static Date strToDateYmd(String date) {
        String format = "yyyy-MM-dd";
        return DateUtil.parse(date,format);
    }
    public static Date strToDate(String date) {
        String format = "yyyy-MM-dd HH:mm:ss";
        return DateUtil.parse(date,format);
    }
    public static List<Date> findDates(Date dBegin, Date dEnd) {
        List lDate = new ArrayList();
        lDate.add(dBegin);
        Calendar cBegin = Calendar.getInstance();
        Calendar cEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        cBegin.setTime(dBegin);
        cEnd.setTime(dEnd);
        cEnd.add(Calendar.DAY_OF_MONTH,-2);
        // 测试此日期是否在指定日期之后
        while (cEnd.getTime().after(cBegin.getTime())) {
            // 根据日历的规则,为给定的日历字段添加或减去指定的时间量
            cBegin.add(Calendar.DAY_OF_MONTH, 1);
            lDate.add(dateToLast(cBegin.getTime()));
        }
        return lDate;
    }
    public static List<DateParam> findEveryDays(Date dBegin, Date dEnd) {
        List<DateParam> params = new ArrayList();
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calBegin.setTime(dBegin);
        Calendar calEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calEnd.setTime(dEnd);
        calEnd.add(Calendar.DAY_OF_MONTH,-2);
        // 判断两个时间是否为同一天
        if (!DateUtil.isSameDay(dBegin, dEnd)) {
            DateParam first = new DateParam();
            first.setStartTime(dBegin);
            first.setEndTime(dateToLast(dBegin));
            params.add(first);
        }
        // 测试此日期是否在指定日期之后
        while (calEnd.getTime().after(calBegin.getTime())) {
            DateParam res = new DateParam();
            // 根据日历的规则,为给定的日历字段添加或减去指定的时间量
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            res.setEndTime(dateToLast(calBegin.getTime()));
            res.setStartTime(dateToFast(calBegin.getTime()));
            params.add(res);
        }
        DateParam last = new DateParam();
        last.setStartTime(dateToFast(dEnd));
        last.setEndTime(dEnd);
        params.add(last);
        return params;
    }
    public static Date dateToFast(Date date) {
        return dateToFastOrLast(date,1);
    }
    public static Date dateToLast(Date date) {
       return dateToFastOrLast(date,2);
    }
    /**
     * 获取传入时间的前一天的初始和结束时间
     */
    public static Date getBeforeDate(Date date){
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        instance.add(Calendar.DATE, -1);
        return instance.getTime();
    }
    /**
     * 根据传入日期获取t天前的开始和结束日期
     * @param t 具体天数 >0 则为当前日期后几天,反之为前几天
     * @return
     */
    public static DateVO getDay(int t) {
        LocalDate localDate = LocalDate.now();
        if (t > 0) {
            localDate = localDate.plusDays(Math.abs(t));
        } else {
            localDate = localDate.minusDays(Math.abs(t));
        }
        LocalDateTime min = LocalDateTime.of(localDate, LocalTime.MIN);
        Date minDate = Date.from(min.atZone(ZoneId.systemDefault()).toInstant());
        LocalDateTime max = LocalDateTime.of(localDate, LocalTime.MAX);
        Date maxDate = Date.from(max.atZone(ZoneId.systemDefault()).toInstant());
        DateVO dateVO = new DateVO(minDate, maxDate);
        return dateVO;
    }
    /**
     * 获取传入时间的前n年时间点
     * @param n 例如: n = -1 表示当前时间的前一年, n = 1 表示获取后一年
     */
    public static Date getBeforeYear(Date date, int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, n);
        return calendar.getTime();
    }
    /**
     * 获取传入时间的前n月时间点
     * @param n 例如: n = -1 表示当前时间的前一月, n = 1 表示获取后一月
     */
    public static Date getBeforeOrNextNumMonth(Date date, int n) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        instance.add(Calendar.MONTH, n);
        return instance.getTime();
    }
    /**
     * 获取传入时间的前n天时间点
     * @param n 例如: n = -1 表示当前时间的前一天, n = 1 表示获取后一天
     */
    public static Date getBeforeDay(Date date, int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, n);
        return calendar.getTime();
    }
    public static String dateToString(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }
    /**
     *
     * @param date 2020-06-12 15:00:00
     * @param type 1 date 的开始时间例如: 2020-06-12 00:00:00
     *             2 date 的结束时间例如: 2020-06-12 23:59:59
     * @return
     */
    public static Date dateToFastOrLast(Date date, Integer type) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int y = c.get(Calendar.YEAR);
        int m = c.get(Calendar.MONTH ) + 1;
        int d = c.get(Calendar.DAY_OF_MONTH);
        String dateStr = "";
        if (Objects.equals(1,type)){
            dateStr = y + "-" + m + "-" + d +" " + 00 + ":"+ 00 + ":" + 00;
        } else {
            dateStr = y + "-" + m + "-" + d +" " + 23 + ":"+ 59 + ":" + 59;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date parse = sdf.parse(dateStr);
            c.setTime(parse);
        }catch (ParseException e) {
            System.out.println("解析异常");
        }
        return c.getTime();
    }
    public static List<DateParam> getMonthBetweenStartTimeAndEndTime(Date startTime, Date endTime) {
        List<DateParam> monthBetween = getMonthBetween(startTime, endTime);
        if (monthBetween.size() == 0) {
            DateParam param = new DateParam();
            param.setStartTime(startTime);
            param.setEndTime(endTime);
            monthBetween.add(param);
            return monthBetween;
        }
        if (monthBetween.size() == 1) {
            DateParam param = monthBetween.get(0);
            param.setEndTime(endTime);
            monthBetween.set(0,param);
            return monthBetween;
        }
        DateParam param = monthBetween.get(0);
        param.setStartTime(startTime);
        DateParam last = monthBetween.get(monthBetween.size() - 1);
        last.setEndTime(endTime);
        monthBetween.set(0,param);
        monthBetween.set(monthBetween.size()-1,last);
        return monthBetween;
    }
    public static List<DateParam> getMonthBetween(Date minDate, Date maxDate){
        List<DateParam> res = new ArrayList<>();
        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();
        min.setTime(minDate);
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);
        max.setTime(maxDate);
        max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);
        Calendar curr = min;
        while (curr.before(max)) {
            DateParam param = new DateParam();
            Date time = curr.getTime();
            param.setStartTime(getMonthFirstOrLastDay(time,0));
            param.setEndTime(getMonthFirstOrLastDay(time,1));
            res.add(param);
            curr.add(Calendar.MONTH, 1);
        }
        return res;
    }
    public static int countMonthNumBetweenDate(Date startTime, Date endTime) {
        Calendar min = Calendar.getInstance();
        min.setTime(startTime);
        Calendar max = Calendar.getInstance();
        max.setTime(endTime);
        int year =max.get(Calendar.YEAR) - min.get(Calendar.YEAR);
        //开始日期若小月结束日期
        if(year < 0){
            year = -year;
            return year*12 + min.get(Calendar.MONTH) - max.get(Calendar.MONTH);
        }
        return year*12 + max.get(Calendar.MONTH) - min.get(Calendar.MONTH);
    }
//    public static int countDayBetweenDate(Date startTime, Date endTime) {
//        long day = DateUtil.betweenDay(startTime, endTime, true);
//        return Integer.valueOf(String.valueOf(day));
//    }
    /**
     * @param date 传入的时间点  2020-03-12 15:30:00
     * @param type 0 获取传入时间的月份开始时间 2020-03-01 00:00:00
     *             1 获取传入时间的月份最后一天的时刻 2020-03-31 23:59:59
     * @return date
     */
    public static  Date getMonthFirstOrLastDay(Date date,Integer type) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        if (Objects.equals(0,type)){
            // 获取传入时间的月份的第一天 yyyy-MM-dd 00:00:00
            c.add(Calendar.MONTH,0);
            c.set(Calendar.DAY_OF_MONTH,1);
            c.set(Calendar.HOUR_OF_DAY,00);
            c.set(Calendar.MINUTE,00);
            c.set(Calendar.SECOND,00);
        } else {
            // 获取传入时间的月份的最后一天 yyyy-MM-dd 23:59:59
            c.add(Calendar.MONTH,1);
            c.set(Calendar.DAY_OF_MONTH,0);
            c.set(Calendar.HOUR_OF_DAY,23);
            c.set(Calendar.MINUTE,59);
            c.set(Calendar.SECOND,59);
        }
        return c.getTime();
    }
    /**
     * 开始时间和结束时间的时间差n天
     * 结束时间是开始时间,开始时间的前n天作为开始时间
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 参数
     */
    public static DateParam getPreDateByRangeTime(Date startTime, Date endTime) {
        DateParam param = new DateParam();
        long days = DateUtil.between(startTime, endTime, DateUnit.DAY);
        DateTime dateTime = DateUtil.offsetDay(startTime, -(int) days);
        param.setStartTime(DateUtil.beginOfDay(dateTime));
        param.setEndTime(DateUtil.endOfDay(startTime));
        return param;
    }
    public static boolean flagIn30DayDate(String str) {
        String YYYY_MM_DD = "yyyy-MM-dd";
        int day = -30;
        boolean convertSuccess = false;
        //时间格式定义
        SimpleDateFormat format = new SimpleDateFormat(YYYY_MM_DD);
        //获取当前时间日期--nowDate
        String nowDate = format.format(new Date());
        //获取30天前的时间日期--minDate
        Calendar calc = Calendar.getInstance();
        calc.add(Calendar.DAY_OF_MONTH, day);
        String minDate = format.format(calc.getTime());
        try {
            //设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期,比如2007/02/29会被接受,并转换成2007/03/01
            format.setLenient(false);
            //获取字符串转换后的时间--strDate
            String strDates = format.format(format.parse(str));
            if (nowDate.compareTo(strDates) >= 0 && strDates.compareTo(minDate) >= 0){
                convertSuccess = true;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return convertSuccess;
    }
    /**
     * localDateTime转Date
     * @param localDateTime
     * @return
     */
    public static Date toDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }
    /**
     * 获取本周开始时间
     */
    public static Date getCurrentWeekStartTimes(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return cal.getTime();
    }
    /**
     * 获取本周结束时间
     */
    public static Date getCurrentWeekEndTimes(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getCurrentWeekStartTimes(date));
        cal.add(Calendar.DAY_OF_WEEK, 6);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }
    /**
     * 获取当年的开始时间戳
     *
     * @return
     */
    public static Date getCurrentYearStartTime(Date date) {
        Calendar calendar = Calendar.getInstance();// 获取当前日期
        calendar.setTimeInMillis(date.getTime());
        calendar.add(Calendar.YEAR, 0);
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_YEAR, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
    /**
     * 获取当年的最后时间戳
     *
     * @return
     */
    public static Date getCurrentYearEndTime(Date date) {
        Calendar calendar = Calendar.getInstance();// 获取当前日期
        calendar.setTimeInMillis(date.getTime());
        int year = calendar.get(Calendar.YEAR);
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        return calendar.getTime();
    }
    /**
     * 获取当天剩余时间(秒)
     * @return
     */
    public static long getCurrentDayEndSec() {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 设置当天结束的时间为23:59:59
        LocalDateTime endOfDay = now.withHour(23).withMinute(59).withSecond(59);
        // 如果当前时间已经超过23:59:59,则应该计算到明天的结束时间
        if (now.toLocalTime().isAfter(LocalTime.of(23, 59, 59))) {
            endOfDay = endOfDay.plusDays(1);
        }
        // 计算时间差
        long duration = ChronoUnit.SECONDS.between(now, endOfDay);
        return duration;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/GraphUtils.java
New file
@@ -0,0 +1,206 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import org.apache.commons.collections4.CollectionUtils;
import java.util.List;
import java.util.Objects;
/**
 * 用于点与多边形位置关系的判断
 *
 * @author lhd
 * @date 2020-5-22 上午09:59:35
 */
public class GraphUtils {
   public static int TWO = 2;
   /**
    * 判断点是否在多边形内(基本思路是用交点法)
    *
    * @param point
    * @param boundaryPoints
    * @return
    */
   public static boolean isPointInPolygon(BmapPoint point, List<BmapPoint> boundaryPoints) {
      if(CollectionUtils.isEmpty(boundaryPoints) || Objects.isNull(point)){
         return false;
      }
      int pointCount = boundaryPoints.size();
      // 首先判断点是否在多边形的外包矩形内,如果在,则进一步判断,否则返回false
      if (!isPointInRectangle(point, boundaryPoints)) {
         return false;
      }
      // 如果点与多边形的其中一个顶点重合,那么直接返回true
      for (BmapPoint boundaryPoint : boundaryPoints) {
         if (point.equals(boundaryPoint)) {
            return true;
         }
      }
      /*
        基本思想是利用X轴射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则在多边形内。还会考虑一些特殊情况,如点在多边形顶点上
        , 点在多边形边上等特殊情况。
       */
      // X轴射线与多边形的交点数
      int intersectPointCount = 0;
      // X轴射线与多边形的交点权值
      float intersectPointWeights = 0;
      // 浮点类型计算时候与0比较时候的容差
      double precision = 2e-10;
      // 边P1P2的两个端点
      BmapPoint point1 = boundaryPoints.get(0), point2;
      // 循环判断所有的边
      for (int i = 1; i <= pointCount; i++) {
         point2 = boundaryPoints.get(i % pointCount);
         /*
           如果点的y坐标在边P1P2的y坐标开区间范围之外,那么不相交。
          */
         if (point.getLat() < Math.min(point1.getLat(), point2.getLat())
                 || point.getLat() > Math.max(point1.getLat(), point2.getLat())) {
            point1 = point2;
            continue;
         }
         /*
           此处判断射线与边相交
          */
         // 如果点的y坐标在边P1P2的y坐标开区间内
         if (point.getLat() > Math.min(point1.getLat(), point2.getLat())
                 && point.getLat() < Math.max(point1.getLat(), point2.getLat())) {
            // 若边P1P2是垂直的
            if (point1.getLng() == point2.getLng()) {
               if (point.getLng() == point1.getLng()) {
                  // 若点在垂直的边P1P2上,则点在多边形内
                  return true;
               } else if (point.getLng() < point1.getLng()) {
                  // 若点在在垂直的边P1P2左边,则点与该边必然有交点
                  ++intersectPointCount;
               }
            } else {
               // 若边P1P2是斜线
               // 点point的x坐标在点P1和P2的左侧
               if (point.getLng() <= Math.min(point1.getLng(), point2.getLng())) {
                  ++intersectPointCount;
                  // 点point的x坐标在点P1和P2的x坐标中间
               } else if (point.getLng() > Math.min(point1.getLng(), point2.getLng())
                       && point.getLng() < Math.max(point1.getLng(), point2.getLng())) {
                  double slopeDiff = 0.0d;
                  if (point1.getLat() > point2.getLat()) {
                     slopeDiff = (point.getLat() - point2.getLat()) / (point.getLng() - point2.getLng())
                             - (point1.getLat() - point2.getLat()) / (point1.getLng() - point2.getLng());
                  } else {
                     slopeDiff = (point.getLat() - point1.getLat()) / (point.getLng() - point1.getLng())
                             - (point2.getLat() - point1.getLat()) / (point2.getLng() - point1.getLng());
                  }
                  if (slopeDiff > 0) {
                     // 由于double精度在计算时会有损失,故匹配一定的容差。经试验,坐标经度可以达到0.0001
                     if (slopeDiff < precision) {
                        // 点在斜线P1P2上
                        return true;
                     } else {
                        // 点与斜线P1P2有交点
                        intersectPointCount++;
                     }
                  }
               }
            }
         } else {
            // 边P1P2水平
            if (point1.getLat() == point2.getLat()) {
               if (point.getLng() <= Math.max(point1.getLng(), point2.getLng())
                       && point.getLng() >= Math.min(point1.getLng(), point2.getLng())) {
                  // 若点在水平的边P1P2上,则点在多边形内
                  return true;
               }
            }
            // 判断点通过多边形顶点
            boolean res = ((point.getLat() == point1.getLat() && point.getLng() < point1.getLng()))
                    || (point.getLat() == point2.getLat() && point.getLng() < point2.getLng());
            if (res) {
               if (point2.getLat() < point1.getLat()) {
                  intersectPointWeights += -0.5;
               } else if (point2.getLat() > point1.getLat()) {
                  intersectPointWeights += 0.5;
               }
            }
         }
         point1 = point2;
      }
      // 偶数在多边形外
      // 奇数在多边形内
      return (intersectPointCount + Math.abs(intersectPointWeights)) % TWO != 0;
   }
   /**
    * 判断点是否在矩形内在矩形边界上,也算在矩形内(根据这些点,构造一个外包矩形)
    *
    * @param point
    *            点对象
    * @param boundaryPoints
    *            矩形边界点
    * @return
    */
   public static boolean isPointInRectangle(BmapPoint point, List<BmapPoint> boundaryPoints) {
      // 西南角点
      BmapPoint southWestPoint = getSouthWestPoint(boundaryPoints);
      // 东北角点
      BmapPoint northEastPoint = getNorthEastPoint(boundaryPoints);
      return (point.getLng() >= southWestPoint.getLng() && point.getLng() <= northEastPoint.getLng()
              && point.getLat() >= southWestPoint.getLat() && point.getLat() <= northEastPoint.getLat());
   }
   /**
    * 根据这组坐标,画一个矩形,然后得到这个矩形西南角的顶点坐标
    *
    * @param vertexs
    * @return
    */
   private static BmapPoint getSouthWestPoint(List<BmapPoint> vertexs) {
      double minLng = vertexs.get(0).getLng(), minLat = vertexs.get(0).getLat();
      for (BmapPoint bmapPoint : vertexs) {
         double lng = bmapPoint.getLng();
         double lat = bmapPoint.getLat();
         if (lng < minLng) {
            minLng = lng;
         }
         if (lat < minLat) {
            minLat = lat;
         }
      }
      return new BmapPoint(minLng, minLat);
   }
   /**
    * 根据这组坐标,画一个矩形,然后得到这个矩形东北角的顶点坐标
    *
    * @param vertexs
    * @return
    */
   private static BmapPoint getNorthEastPoint(List<BmapPoint> vertexs) {
      double maxLng = 0.0d, maxLat = 0.0d;
      for (BmapPoint bmapPoint : vertexs) {
         double lng = bmapPoint.getLng();
         double lat = bmapPoint.getLat();
         if (lng > maxLng) {
            maxLng = lng;
         }
         if (lat > maxLat) {
            maxLat = lat;
         }
      }
      return new BmapPoint(maxLng, maxLat);
   }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/HandCardUtil.java
New file
@@ -0,0 +1,42 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import cn.hutool.core.lang.Snowflake;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
 * 进制转换工具,最大支持十进制和DICT.length()进制的转换
 * 1、将十进制的数字转换为指定进制的字符串;
 * 2、将其它进制的数字(字符串形式)转换为十进制的数字
 * @author xuliugen
 * @date 2018/04/23
 */
@Component
public class HandCardUtil {
    /**
     * 获取随机串码
     * @param
     * @return
     */
    public static String getHandCard() {
        UUID uuid = UUID.randomUUID();
        String str = uuid.toString().replace("-", "").substring(0, 20);
        return str;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/HttpContextUtils.java
New file
@@ -0,0 +1,79 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import com.yami.shop.common.exception.YamiShopBindException;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
 * @author LGH
 */
@Slf4j
@UtilityClass
public class HttpContextUtils{
    /**
     * 请求字符串的最大长度 1m
     */
    public static final int MAX_STRING_SIZE = 1024 * 1024;
    public HttpServletRequest getHttpServletRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }
    public String getDomain(){
        HttpServletRequest request = getHttpServletRequest();
        StringBuffer url = request.getRequestURL();
        return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
    }
    public String getOrigin(){
        HttpServletRequest request = getHttpServletRequest();
        return request.getHeader("Origin");
    }
    public String getStringFromStream(HttpServletRequest req) {
        if (req.getContentLength() > MAX_STRING_SIZE) {
            // 请求数据过长
            throw new YamiShopBindException("yami.request.data.too.long");
        }
        ServletInputStream is;
        try {
            is = req.getInputStream();
            int nRead = 1;
            int nTotalRead = 0;
            byte[] bytes = new byte[1024];
            while (nRead > 0) {
                nRead = is.read(bytes, nTotalRead, bytes.length - nTotalRead);
                if (nRead > 0) {
                    nTotalRead = nTotalRead + nRead;
                }
            }
            if (nTotalRead > MAX_STRING_SIZE) {
                // 请求数据过长
                throw new YamiShopBindException("yami.request.data.too.long");
            }
            return new String(bytes, 0, nTotalRead, StandardCharsets.UTF_8);
        } catch (IOException e) {
            log.error("IOException:", e);
            return "";
        }
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/IPHelper.java
New file
@@ -0,0 +1,46 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import javax.servlet.http.HttpServletRequest;
/**
 * IP帮助工具
 * @author yami
 */
public class IPHelper {
    private static final String UNKNOWN = "unknown";
    /**
     * 得到用户的真实地址,如果有多个就取第一个
     *
     * @return
     */
    public static String getIpAddr() {
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        if (request == null) {
            return null;
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        String[] ips = ip.split(",");
        return ips[0].trim();
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/IdCardCheck.java
New file
@@ -0,0 +1,148 @@
package com.yami.shop.common.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
public class IdCardCheck {
    /*
    在lesson02中设计一个名字为IdCardCheck.java类,实现从键盘 输入一个身份证号码字符串,
    判断输入的字符串是否符合身份证号码的规则,如果符合,计算输出年龄 输出它的年龄,输出你
    出生在那一年的第几周以及出生到现在已经经过了几周了。如果不符合,提示,并让其重新输入。
    直到输入正确省份证号码为止
     */
    //441225200002312559 //检验码正确,但2月份没有31天
    //441225201012092558 //生成的正确格式的身份证号码
    public void test() throws ParseException {
        Scanner sc = new Scanner(System.in);
        String idNum;
        do {
            System.out.println("请输入身份证号码:");
            idNum = sc.nextLine();
        } while (!checkIdCardNum(idNum));
        System.out.println("身份证号码\"" + idNum + "\"正确!");
        System.out.println("持卡人的年龄:" + getYear(idNum));
        System.out.println("出生的所在那一周是出生那年的第 " + getBirthWeek(idNum) + " 周");
        System.out.println("从出生到现在过去了 " + getWeeks(idNum) + " 周");
    }
    //身份证号码的严格校验
    public boolean checkIdCardNum(String idNum) throws ParseException {
        idNum = idNum.toUpperCase(); //将末尾可能存在的x转成X
        String regex = "";
        regex += "^[1-6]\\d{5}"; //前6位地址码。后面仍需打表校验
        regex += "(18|19|20)\\d{2}"; //年份。后面仍需校验
        regex += "((0[1-9])|(1[0-2]))"; //月份。后面仍需校验
        regex += "(([0-2][1-9])|10|20|30|31)"; //日期。后面仍需校验
        regex += "\\d{3}"; //3位顺序码
        regex += "[0-9X]"; //检验码。后面仍需验证
        if (!idNum.matches(regex))
            return false;
        //第1,2位(省)打表进一步校验
        int[] d = {11, 12, 13, 14, 15,
                21, 22, 23, 31, 32, 33, 34, 35, 36, 37,
                41, 42, 43,
                44, 45, 46,
                50, 51, 52, 53, 53,
                61, 62, 63, 64, 65,
                83, 81, 82};
        boolean flag = false;
        int prov = Integer.parseInt(idNum.substring(0, 2));
        for (int i = 0; i < d.length; i++)
            if (d[i] == prov) {
                flag = true;
                break;
            }
        if (!flag)
            return false;
        //生日校验:生日的时间不能比当前时间(指程序检测用户输入的身份证号码的时候)晚
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date birthDate = sdf.parse(idNum.substring(6, 14));
        Date curDate = new Date();
        if (birthDate.getTime() > curDate.getTime())
            return false;
        //生日校验:每个月的天数不一样(有的月份没有31),还要注意闰年的二月
        int year = Integer.parseInt(idNum.substring(6, 10));
        int leap = ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ? 1 : 0;
        final int[] month = {0, 31, 28 + leap, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        int mon = Integer.parseInt(idNum.substring(10, 12));
        int day = Integer.parseInt(idNum.substring(12, 14));
        if (day > month[mon]) {
            //System.out.println(day+" "+month[mon]+"\n");
            //System.out.println("---");
            return false;
        }
        //检验码
        if (idNum.charAt(17) != getLastChar(idNum))
            return false;
        return true;
    }
    //根据身份证号码的前17位计算校验码
    public char getLastChar(String idNum) //由于这个功能比较独立,就分离出来
    {
        final int[] w = {0, 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        final char[] ch = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}; //这就是为什么一开始将末尾可能存在的x转成X的原因
        int res = 0;
        for (int i = 0; i < 17; i++) {
            int t = idNum.charAt(i) - '0';
            res += (t * w[i + 1]);
        }
        return ch[res % 11];
    }
    //根据身份证号码的出生日期计算年龄
    public int getYear(String idNum) {
        int yearBirth = Integer.parseInt(idNum.substring(6, 10));
        int monBirth = Integer.parseInt(idNum.substring(10, 12));
        int dayBirth = Integer.parseInt(idNum.substring(12, 14));
        Calendar cur = Calendar.getInstance();
        int yearCur = cur.get(Calendar.YEAR);
        int monCur = cur.get(Calendar.MONTH) + 1; //不要忘了+1
        int dayCur = cur.get(Calendar.DATE);
        //System.out.println(yearCur+" "+monCur+" "+dayCur);
        int age = yearCur - yearBirth;
        if (monCur < monBirth || (monCur == monBirth && dayCur < dayBirth))
            age--;
        return age;
    }
    //出生的所在那一周是出生那年的第几周
    public int getBirthWeek(String idNum) throws ParseException, ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date birthDate = sdf.parse(idNum.substring(6, 14));  //默认0时0分0秒
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(birthDate);
        return calendar.get(Calendar.WEEK_OF_YEAR);
    }
    //从出生到现在过去了多少周
    public int getWeeks(String idNum) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date birthDate = sdf.parse(idNum.substring(6, 14));  //默认0时0分0秒
        Date curDate = new Date();
        return (int) ((curDate.getTime() - birthDate.getTime()) / (long) (7 * 24 * 60 * 60 * 1000)); //不建议把分子转成int,可能会溢出
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/IdUtil.java
New file
@@ -0,0 +1,92 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import cn.hutool.core.lang.Snowflake;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
 * 进制转换工具,最大支持十进制和DICT.length()进制的转换
 * 1、将十进制的数字转换为指定进制的字符串;
 * 2、将其它进制的数字(字符串形式)转换为十进制的数字
 * @author xuliugen
 * @date 2018/04/23
 */
@Component
public class IdUtil {
    @Autowired(required = false)
    private Snowflake snowflake;
    private static final String DICT = "0123456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
    private static final int SEED = DICT.length();
    private static final int ID_MIN_LENGTH = 6;
    /**
     * 数字->字符映射
     */
    private static final char[] CHARS = DICT.toCharArray();
    /**
     * 字符->数字映射
     */
    private static final Map<Character, Integer> NUMBERS = new HashMap<>();
    static {
        int len = CHARS.length;
        for (int i = 0; i<len; i++) {
            NUMBERS.put(CHARS[i], i);
        }
    }
    /**
     * 根据从数据库中返回的记录ID生成对应的短网址编码
     * @param id (1-56.8billion)
     * @return
     */
    public static String encode(long id) {
        StringBuilder shortUrl = new StringBuilder();
        while (id > 0) {
            int r = (int) (id % SEED);
            shortUrl.insert(0, CHARS[r]);
            id = id / SEED;
        }
        int len = shortUrl.length();
        while (len < ID_MIN_LENGTH) {
            shortUrl.insert(0, CHARS[0]);
            len++;
        }
        return shortUrl.toString();
    }
    /**
     * 根据获得的短网址编码解析出数据库中对应的记录ID
     * @param key 短网址 eg. RwTji8, GijT7Y等等
     * @return
     */
    public static long decode(String key) {
        char[] shorts = key.toCharArray();
        int len = shorts.length;
        long id = 0L;
        for (int i = 0; i < len; i++) {
            id = id + (long) (NUMBERS.get(shorts[i]) * Math.pow(SEED, len-i-1));
        }
        return id;
    }
    public String nextShortId() {
        return encode(snowflake.nextId());
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/ImageUtil.java
New file
@@ -0,0 +1,98 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import cn.hutool.core.util.StrUtil;
import com.yami.shop.common.exception.YamiShopBindException;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Objects;
/**
 * 图片处理工具类
 * @author yami
 */
public class ImageUtil {
    /**
     * 将图片转为二进制数组
     * @param imgUrl
     * @return
     */
    public static byte[] imgToBinary(String imgUrl) {
        try {
            BufferedImage bufferedImage = ImageIO.read(new URL(imgUrl));
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            String suffix = imgUrlFileType(imgUrl);
            //ImageIO无法写入jpeg文件 报Invalid argument to native writeImage,需重画
            if(StrUtil.equals(suffix, "jpg") || StrUtil.equals(suffix, "jpeg")){
                BufferedImage tag;
                tag = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), BufferedImage.TYPE_INT_BGR);
                Graphics g = tag.getGraphics();
                g.drawImage(bufferedImage, 0, 0, null);
                g.dispose();
                bufferedImage = tag;
            }
            ImageIO.write(bufferedImage, suffix, baos);
            byte[] bytes = baos.toByteArray();
            return bytes;
        } catch (IOException e) {
            // 图片丢失,请重新上传图片
            throw new YamiShopBindException("yami.img.lose");
        }
    }
    /**
     * @param imgUrl
     * @return 文件得后缀,文件类型 jpg ,  png , ...
     */
    public static String imgUrlFileType(String imgUrl) {
        if (StrUtil.isBlank(imgUrl)) {
            return imgUrl;
        }
        imgUrl.trim();
        String[] split = imgUrl.split("\\.");
        String s = split[split.length - 1];
        return s;
    }
    /**
     * @param imgUrl
     * @return 获取文件名称
     */
    public static String imgUrlFileName(String imgUrl) {
        if (StrUtil.isBlank(imgUrl)) {
            return imgUrl;
        }
        imgUrl.trim();
        String[] split = imgUrl.split("/");
        String s = split[split.length - 1];
        return s;
    }
    /**
     * @param imgUrl
     * @return 获取文件名称 45d3631e97d8438d80f9db1369595b8c
     */
    public static String imgUrlFileNameNoSuffix(String imgUrl) {
        if (StrUtil.isBlank(imgUrl)) {
            return imgUrl;
        }
        imgUrl.trim();
        String[] split = imgUrl.split("/");
        String s = split[split.length - 1];
        String[] split1 = s.split("\\.");
        return split1[0];
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/Json.java
New file
@@ -0,0 +1,182 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.json.JsonWriteFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
 * json 工具类
 * @author yami
 */
@Slf4j
public class Json {
    private static ObjectMapper objectMapper = new ObjectMapper();
    static {
        // 是否缩放排列输出,默认false,有些场合为了便于排版阅读则需要对输出做缩放排列
//        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        // 序列化日期时以timestamps输出,默认true
        // objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        // 序列化枚举是以toString()来输出,默认false,即默认以name()来输出     如:ENUM01("enum_01") 默认为 ENUM01,true则为enum_01
        // objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
        // 序列化枚举是以ordinal()来输出,默认false   如:ENUM01("enum_01") 默认为 ENUM01,true则为 0 非常危险
        // objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX);
        // 序列化Map时对key进行排序操作,默认false
        // objectMapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
        // 序列化char[]时以json数组输出,默认false
        //objectMapper.enable(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS);
        //序列化BigDecimal时之间输出原始数字还是科学计数,默认false,即是否以toPlainString()科学计数方式来输出
        // 1E+20 -> 100000000000000000000
//        objectMapper.enable(Feature.WRITE_BIGDECIMAL_AS_PLAIN);
        // 如果为空则不输出
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        // 对于空的对象转json的时候不抛出错误
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        // 禁用序列化日期为timestamps
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        // 禁用遇到未知属性抛出异常
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 视空字符传为null
//        objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
        // 低层级配置
//        objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        // 允许属性名称没有引号
//        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        // 允许单引号
//        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        // 取消对非ASCII字符的转码
        objectMapper.configure(JsonWriteFeature.ESCAPE_NON_ASCII.mappedFeature(), false);
        // 取消过时objectMapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, false)
        objectMapper.registerModule(new JavaTimeModule());
    }
    /**
     * 对象转json
     * @param object
     * @return
     */
    public static String toJsonString(Object object) {
        try {
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            log.error("对象转json错误:", e);
        }
        return null;
    }
    /**
     * json转对象
     * @param json
     * @param clazz
     * @return
     */
    public static <T> T parseObject(String json, Class<T> clazz) {
        if (json == null) {
            return null;
        }
        T result = null;
        try {
            result = objectMapper.readValue(json, clazz);
        } catch (Exception e) {
            log.error("json转对象错误:", e);
        }
        return result;
    }
    /**
     * json转换换成对象
     * @param src src
     * @param clazz clazz
     * @return Class
     */
    public static <T> T parseObject(byte[] src, Class<T> clazz) {
        T result = null;
        try {
            result = objectMapper.readValue(src, clazz);
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("parseObject() error: {}", e.getMessage());
        }
        return result;
    }
    public static ObjectMapper getObjectMapper() {
        return objectMapper;
    }
    /**
     *      * https://stackoverflow.com/questions/6349421/how-to-use-jackson-to-deserialise-an-array-of-objects
     *      * List<MyClass> myObjects = Arrays.asList(mapper.readValue(json, MyClass[].class))
     *      * works up to 10 time faster than TypeRefence.
     * @return
     */
    public static <T> List<T> parseArray(String json, Class<T[]> clazz){
        if (json == null) {
            return null;
        }
        T[] result = null;
        try {
            result = objectMapper.readValue(json, clazz);
        } catch (Exception e) {
            log.error("Exception:", e);
        }
        if (result == null) {
            return Collections.emptyList();
        }
        return Arrays.asList(result);
    }
    /**
     * 转换成json节点,即map
     * @param jsonStr
     * @return
     */
    public static JsonNode parseJson(String jsonStr) {
        if (jsonStr == null) {
            return null;
        }
        JsonNode jsonNode = null;
        try {
            jsonNode = objectMapper.readTree(jsonStr);
        } catch (Exception e) {
            log.error("Exception:", e);
        }
        return jsonNode;
    }
//    public static void main(String[] args){
//        String arr = "[1.01,1.03,1.23]";
//
//        List<Double> doubles = parseArray(arr, Double[].class);
//        for (Double aDouble : doubles) {
//            System.out.println(aDouble);
//        }
//
//    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/PageAdapter.java
New file
@@ -0,0 +1,32 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import cn.hutool.core.util.PageUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
/**
 * 分页适配
 * @author LGH
 */
@Data
public class PageAdapter{
    private int begin;
    private int size;
    public PageAdapter(Page page) {
        int[] startEnd = PageUtil.transToStartEnd((int) page.getCurrent() - 1, (int) page.getSize());
        this.begin = startEnd[0];
        this.size = (int)page.getSize();
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/PageParam.java
New file
@@ -0,0 +1,167 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springdoc.api.annotations.ParameterObject;
import java.util.Collections;
import java.util.List;
/**
 * 分页参数
 * @author yami
 */
@Schema
@ParameterObject
public class PageParam<T> extends Page<T> {
    /**
     * 每页显示条数,默认 10
     */
    @Schema(description = "每页大小,默认10")
    private long size = 10;
    /**
     * 当前页
     */
    @Schema(description = "当前页,默认1")
    private long current = 1;
    /**
     * 查询数据列表
     */
    @Hidden
    private List<T> records;
    /**
     * 总数
     */
    @Hidden
    private long total = 0;
    /**
     * 是否进行 count 查询
     */
    @Hidden
    private boolean isSearchCount = true;
    @Hidden
    private String countId;
    @Hidden
    private Long maxLimit;
    @Hidden
    private boolean optimizeCountSql;
    @Hidden
    private List<OrderItem> orders;
    @Override
    public List<T> getRecords() {
        return this.records;
    }
    @Override
    public Page<T> setRecords(List<T> records) {
        this.records = records;
        return this;
    }
    @Override
    public long getTotal() {
        return this.total;
    }
    @Override
    public Page<T> setTotal(long total) {
        this.total = total;
        return this;
    }
    @Hidden
    public boolean getSearchCount() {
        if (total < 0) {
            return false;
        }
        return isSearchCount;
    }
    @Override
    public boolean isSearchCount() {
        if (total < 0) {
            return false;
        }
        return isSearchCount;
    }
    @Override
    public Page<T> setSearchCount(boolean isSearchCount) {
        this.isSearchCount = isSearchCount;
        return this;
    }
    @Override
    public long getSize() {
        return this.size;
    }
    @Override
    public Page<T> setSize(long size) {
        if (size > 100) {
            this.size = 100;
        } else {
            this.size = size;
        }
        return this;
    }
    @Override
    public long getCurrent() {
        return this.current;
    }
    @Override
    public Page<T> setCurrent(long current) {
        this.current = current;
        return this;
    }
    @Override
    public void setOrders(List<OrderItem> orders) {
        super.setOrders(Collections.emptyList());
    }
    /** @deprecated */
    @Deprecated
    public String getCountId() {
        return this.countId;
    }
    /** @deprecated */
    @Deprecated
    public Long getMaxLimit() {
        return this.maxLimit;
    }
    /** @deprecated */
    @Deprecated
    public List<OrderItem> getOrders() {
        return this.orders;
    }
    /** @deprecated */
    @Deprecated
    public boolean isOptimizeCountSql() {
        return this.optimizeCountSql;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/PayUtil.java
New file
@@ -0,0 +1,33 @@
package com.yami.shop.common.util;
import org.springframework.stereotype.Component;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@Component
public class PayUtil {
    public static String encryptWithMD5(String password) {
        try {
            // 创建一个MD5的消息摘要对象
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 将密码转换为字节数组并进行MD5摘要
            byte[] messageDigest = md.digest(password.getBytes());
            // 将摘要转换为16进制字符串
            BigInteger no = new BigInteger(1, messageDigest);
            String hashtext = no.toString(16);
            // 补齐长度到32位
            while (hashtext.length() < 32) {
                hashtext = "0" + hashtext;
            }
            return hashtext;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5 hashing algorithm not found", e);
        }
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/PoiExcelUtil.java
New file
@@ -0,0 +1,270 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelWriter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.apache.poi.xssf.usermodel.XSSFDataValidationConstraint;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/**
 * 功能: poi导出excel工具类
 *
 * @author lhd
 */
@Slf4j
public class PoiExcelUtil {
    /**
     * 合并单元格处理,获取合并行
     *
     * @param sheet
     * @return List<CellRangeAddress>
     */
    public static List<CellRangeAddress> getCombineCell(Sheet sheet) {
        List<CellRangeAddress> list = new ArrayList<CellRangeAddress>();
        // 获得一个 sheet 中合并单元格的数量
        int sheetmergerCount = sheet.getNumMergedRegions();
        // 遍历所有的合并单元格
        for (int i = 0; i < sheetmergerCount; i++) {
            // 获得合并单元格保存进list中
            CellRangeAddress ca = sheet.getMergedRegion(i);
            list.add(ca);
        }
        return list;
    }
    public static int getRowNum(List<CellRangeAddress> listCombineCell, Cell cell, Sheet sheet) {
        int xr = 0;
        int firstC = 0;
        int lastC = 0;
        int firstR = 0;
        int lastR = 0;
        for (CellRangeAddress ca : listCombineCell) {
            // 获得合并单元格的起始行, 结束行, 起始列, 结束列
            firstC = ca.getFirstColumn();
            lastC = ca.getLastColumn();
            firstR = ca.getFirstRow();
            lastR = ca.getLastRow();
            if (cell.getRowIndex() >= firstR && cell.getRowIndex() <= lastR) {
                if (cell.getColumnIndex() >= firstC && cell.getColumnIndex() <= lastC) {
                    xr = lastR;
                }
            }
        }
        return xr;
    }
    /**
     * 简单格式化校验,返回字符串类型,如果是int类型还需进行处理,Double.valueOf(value).intValue()
     *
     * @param row     行数据
     * @param cellNum 单元格
     * @param isNum   是否为数值类型
     * @return
     */
    public static String getRowValue(Row row, Integer cellNum, Boolean isNum) {
        // 单品名称
        String value = null;
        CellType cellType = null;
        try {
            cellType = row.getCell(cellNum).getCellType();
        } catch (NullPointerException e) {
            return isNum ? "0" : null;
        }
        if (Objects.equals(CellType.NUMERIC, cellType)) {
            if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(row.getCell(cellNum))) {
                Date time = row.getCell(cellNum).getDateCellValue();
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                value = format.format(time);
            } else {
                NumberFormat numberFormat = NumberFormat.getInstance();
                // 不显示千位分割符,否则显示结果会变成类似1,234,567,890
                numberFormat.setGroupingUsed(false);
                double d = row.getCell(cellNum).getNumericCellValue();
                value = numberFormat.format(d);
            }
        } else {
            value = Objects.isNull(row.getCell(cellNum)) ? "" : row.getCell(cellNum).getStringCellValue();
        }
        if (isNum) {
            return StrUtil.isBlank(value) ? "0" : value;
        }
        return value;
    }
    /**
     * 判断指定的单元格是否是合并单元格
     *
     * @param sheet
     * @param row    行下标
     * @param column 列下标
     * @return
     */
    public static boolean isMergedRegion(Sheet sheet, int row, int column) {
        int sheetMergeCount = sheet.getNumMergedRegions();
        for (int i = 0; i < sheetMergeCount; i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            int firstColumn = range.getFirstColumn();
            int lastColumn = range.getLastColumn();
            int firstRow = range.getFirstRow();
            int lastRow = range.getLastRow();
            if (row >= firstRow && row <= lastRow) {
                if (column >= firstColumn && column <= lastColumn) {
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * 如果需要合并的话,就合并
     */
    public static void mergeIfNeed(ExcelWriter writer, int firstRow, int lastRow, int firstColumn, int lastColumn, Object content) {
        if (content instanceof Date) {
            content = DateUtil.format((Date) content, DatePattern.NORM_DATETIME_PATTERN);
        }
        if (lastRow - firstRow > 0 || lastColumn - firstColumn > 0) {
            writer.merge(firstRow, lastRow, firstColumn, lastColumn, content, false);
        } else {
            writer.writeCellValue(firstColumn, firstRow, content);
        }
    }
    public static void writeExcel(HttpServletResponse response, ExcelWriter writer) {
        //response为HttpServletResponse对象
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
        response.setHeader("Content-Disposition", "attachment;filename=1.xlsx");
        ServletOutputStream servletOutputStream = null;
        try {
            servletOutputStream = response.getOutputStream();
            writer.flush(servletOutputStream);
            servletOutputStream.flush();
        } catch (IORuntimeException | IOException e) {
            log.error("写出Excel发生错误:", e);
        } finally {
            IoUtil.close(writer);
        }
    }
    public static void writeExcel(String filename, ExcelWriter writer, HttpServletResponse response) {
        OutputStream ouputStream = null;
        try {
            filename = new String(filename.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-disposition", "attachment;filename=" + filename);
            ouputStream = response.getOutputStream();
            writer.flush(ouputStream);
            ouputStream.flush();
        } catch (Exception e) {
            log.error("写出Excel发生错误:", e);
        } finally {
            IoUtil.close(writer);
        }
    }
    /**
     * 创建下拉列表选项
     *
     * @param workbook 当前写入器
     * @param sheet    所在Sheet页面
     * @param list     下拉框的选项值
     * @param firstRow 起始行(从0开始)
     * @param lastRow  终止行(从0开始)
     * @param firstCol 起始列(从0开始)
     * @param lastCol  终止列(从0开始)
     */
    public static void createDropDownList(Workbook workbook, Sheet sheet, List<String> list, int firstRow, int lastRow, int firstCol, int lastCol) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        int sheetTotal = workbook.getNumberOfSheets();
        // 设置下拉框数据
        // 新建一个sheet,把数据隐藏,从单元格引用就没有255的报错
        String sheetName = "hidden" + sheetTotal;
        Sheet hidden = workbook.getSheet(sheetName);
        if (Objects.isNull(hidden)) {
            hidden = workbook.createSheet(sheetName);
            for (int i = 0; i < list.size(); i++) {
                Row row = hidden.createRow(i);
                Cell cell = row.createCell(0);
                cell.setCellValue(list.get(i));
            }
            workbook.setSheetHidden(sheetTotal, true);
        }
        String strFormula = sheetName + "!$A$1:$A$65535";
        DataValidationConstraint constraint = new XSSFDataValidationConstraint(DataValidationConstraint.ValidationType.LIST, strFormula);
        CellRangeAddressList regions = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);
        DataValidationHelper help = hidden.getDataValidationHelper();
        DataValidation dataValidation = help.createValidation(constraint, regions);
        sheet.addValidationData(dataValidation);
        // Excel兼容性问题
        if (dataValidation instanceof XSSFDataValidation) {
            dataValidation.setSuppressDropDownArrow(true);
            dataValidation.setShowErrorBox(true);
        } else {
            dataValidation.setSuppressDropDownArrow(false);
        }
        sheet.addValidationData(dataValidation);
    }
    /**
     * 创建下拉列表选项【适用长度不会超过255的】
     *
     * @param sheet    所在Sheet页面
     * @param values   下拉框的选项值
     * @param firstRow 起始行(从0开始)
     * @param lastRow  终止行(从0开始)
     * @param firstCol 起始列(从0开始)
     * @param lastCol  终止列(从0开始)
     */
    public static void createDropDownList(Sheet sheet, String[] values, int firstRow, int lastRow, int firstCol, int lastCol) {
        DataValidationHelper helper = sheet.getDataValidationHelper();
        CellRangeAddressList addressList = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);
        // 设置下拉框数据
        DataValidationConstraint constraint = helper.createExplicitListConstraint(values);
        DataValidation dataValidation = helper.createValidation(constraint, addressList);
        // Excel兼容性问题
        if (dataValidation instanceof XSSFDataValidation) {
            dataValidation.setSuppressDropDownArrow(true);
            dataValidation.setShowErrorBox(true);
        } else {
            dataValidation.setSuppressDropDownArrow(false);
        }
        sheet.addValidationData(dataValidation);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/PrincipalUtil.java
New file
@@ -0,0 +1,130 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import cn.hutool.core.util.StrUtil;
import java.util.regex.Pattern;
/**
 * 正则表达式工具
 * @author LGH
 */
public class PrincipalUtil {
    /**
     * 以1开头,后面跟10位数
     */
    public static final String MOBILE_REGEXP = "1[0-9]{10}";
    /**
     * 电话号码
     */
    public static  final String TEL_REGEXP = "([0-9]{3,4}-)?[0-9]{7,8}";
    /**
     * 微信号
     */
    public static  final String WX_NUMBER_REGEXP = "[a-zA-Z][a-zA-Z\\d_-]{5,19}$";
    /**
     * QQ号
     */
    public static  final String QQ_NUMBER_REGEXP = "[1-9][0-9]{4,14}";
    /**
     * 1. 用户名不能为纯数字 2. 由数字字母下划线 4-16位组成
     */
    public static final String USER_NAME_REGEXP = "(?!\\d+$)([a-zA-Z0-9_]{4,16})";
    /**
     * 字段名,数字字母下划线
     */
    public static final String FIELD_REGEXP = "([a-zA-Z0-9_]+)";
    /**
     * 只能输入数字字母
     */
    public static final String WITHOUT_CHINESE = "^[A-Za-z0-9]+$";
    /**
     * 由简单的字母数字拼接而成的字符串 不含有下划线,大写字母
     */
    public static final String SIMPLE_CHAR_REGEXP = "([a-z0-9]+)";
    /**
     * 邮箱正则
     */
    public static final String MAIL_REGEXP = "([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})";
    public static boolean isMobile(String value) {
        if(StrUtil.isBlank(value)) {
            return false;
        }
        return Pattern.matches(MOBILE_REGEXP, value);
    }
    public static boolean isTel(String value) {
        if(StrUtil.isBlank(value)) {
            return false;
        }
        return Pattern.matches(TEL_REGEXP, value);
    }
    public static boolean isWxNumber(String value) {
        if(StrUtil.isBlank(value)) {
            return false;
        }
        return Pattern.matches(WX_NUMBER_REGEXP, value);
    }
    public static boolean isQQNumber(String value) {
        if(StrUtil.isBlank(value)) {
            return false;
        }
        return Pattern.matches(QQ_NUMBER_REGEXP, value);
    }
    public static boolean isUserName(String value) {
        if(StrUtil.isBlank(value)) {
            return false;
        }
        return Pattern.matches(USER_NAME_REGEXP, value);
    }
    public static boolean isMail(String value) {
        if(StrUtil.isBlank(value)) {
            return false;
        }
        return Pattern.matches(MAIL_REGEXP, value);
    }
    /**
     * 是否符合字段规则
     * @param value 输入值
     * @return 匹配结果
     */
    public static boolean isField(String value) {
        return isMatching(FIELD_REGEXP, value);
    }
    public static boolean isMatching(String regexp, String value) {
        if (StrUtil.isBlank(value)) {
            return false;
        }
        return Pattern.matches(regexp, value);
    }
    /**
     * 是否是由简单的字母数字拼接而成的字符串
     * @param value 输入值
     * @return 匹配结果
     */
    public static boolean isSimpleChar(String value) {
        return isMatching(SIMPLE_CHAR_REGEXP, value);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/RedisUtil.java
New file
@@ -0,0 +1,294 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ResponseEnum;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
 * 缓存工具类
 * @author yami
 */
@Slf4j
public class RedisUtil {
    @SuppressWarnings("unchecked")
    private static RedisTemplate<String,Object> redisTemplate = SpringContextUtils.getBean("redisTemplate",RedisTemplate.class);
    public static final StringRedisTemplate STRING_REDIS_TEMPLATE = SpringContextUtils.getBean("stringRedisTemplate",StringRedisTemplate.class);
    private static final Logger logger = LoggerFactory.getLogger(RedisUtil.class);
    //=============================common============================
    /**
     * 指定缓存失效时间
     * @param key 键
     * @param time 时间(秒)
     * @return
     */
    public static Boolean expire(String key,long time){
        try {
            if(time>0){
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            log.error("指定Redis缓存失效时间错误:", e);
            return false;
        }
    }
    /**
     * 根据key 获取过期时间
     * @param key 键 不能为null
     * @return 时间(秒) 返回-1代表为永久有效 失效时间为0,说明该主键未设置失效时间(失效时间默认为-1)
     */
    public static Long getExpire(String key){
        return redisTemplate.getExpire(key,TimeUnit.SECONDS);
    }
    /**
     * 判断key是否存在
     * @param key 键
     * @return true 存在 false 不存在
     */
    public static Boolean hasKey(String key){
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            log.error("判断Redis中指定的key是否存在错误:", e);
            return false;
        }
    }
    /**
     * 删除缓存
     * @param key 可以传一个值 或多个
     */
    @SuppressWarnings("unchecked")
    public static void del(String ... key){
        if(key!=null&&key.length>0){
            if(key.length==1){
                redisTemplate.delete(key[0]);
            }else{
                redisTemplate.delete(Arrays.asList(key));
            }
        }
    }
    /**
     * 删除缓存
     * @param keys key列表
     */
    @SuppressWarnings("unchecked")
    public static void del(List<String> keys){
        if(CollUtil.isEmpty(keys)){
            return;
        }
        redisTemplate.delete(keys);
    }
    //============================String=============================
    /**
     * 普通缓存获取
     * @param key 键
     * @return 值
     */
    @SuppressWarnings("unchecked")
    public static <T> T get(String key){
        return key==null?null:(T)redisTemplate.opsForValue().get(key);
    }
    /**
     * 普通缓存放入并设置时间
     * @param key 键
     * @param value 值
     * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public static boolean set(String key,Object value,long time){
        try {
            if(time>0){
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            }else{
                redisTemplate.opsForValue().set(key, value);
            }
            return true;
        } catch (Exception e) {
            log.error("设置Redis缓存错误:", e);
            return false;
        }
    }
    /**
     * 递增 此时value值必须为int类型 否则报错
     * @param key 键
     * @param delta 要增加几(大于0)
     * @return
     */
    public static Long incr(String key, long delta){
        if(delta<0){
            throw new RuntimeException("递增因子必须大于0");
        }
        return STRING_REDIS_TEMPLATE.opsForValue().increment(key, delta);
    }
    /**
     * 递减
     * @param key 键
     * @param delta 要减少几(小于0)
     * @return
     */
    public static Long decr(String key, long delta){
        if(delta<0){
            throw new RuntimeException("递减因子必须小于0");
        }
        return STRING_REDIS_TEMPLATE.opsForValue().increment(key, -delta);
    }
    public static boolean setLongValue(String key,Long value,long time) {
        try {
            if(time>0){
                STRING_REDIS_TEMPLATE.opsForValue().set(key, String.valueOf(value), time, TimeUnit.SECONDS);
            }else{
                STRING_REDIS_TEMPLATE.opsForValue().set(key, String.valueOf(value));
            }
            return true;
        } catch (Exception e) {
            log.error("设置Redis缓存错误:", e);
            return false;
        }
    }
    /**
     * 普通缓存获取
     * @param key 键
     * @return 值
     */
    public static Long getLongValue(String key){
        if (key == null) {
            return null;
        }
        String result = STRING_REDIS_TEMPLATE.opsForValue().get(key);
        if (result == null) {
            return null;
        }
        return Long.valueOf(result);
    }
    /**
     * 比较和删除标记,原子性
     * @return 是否成功
     */
    public static boolean cad(String key, String value) {
        if (key.contains(StrUtil.SPACE) || value.contains(StrUtil.SPACE)) {
            throw new YamiShopBindException("yami.network.busy");
        }
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        //通过lure脚本原子验证令牌和删除令牌
        Long result = STRING_REDIS_TEMPLATE.execute(new DefaultRedisScript<Long>(script, Long.class),
                Collections.singletonList(key),
                value);
        return !Objects.equals(result, 0L);
    }
    /**
     * 批量删除缓存
     * @param keys
     */
    public static void deleteBatch(List<String> keys) {
        if (CollUtil.isEmpty(keys)) {
            return;
        }
        for (String key : keys) {
            if (key.contains(StrUtil.SPACE)) {
                throw new YamiShopBindException("yami.network.busy");
            }
        }
        redisTemplate.delete(keys);
    }
    public static Set<String> keys(String pattern) {
        return redisTemplate.keys(pattern);
    }
    /**
     * list缓存放入并设置时间
     * @param key 键
     * @param list 值
     * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public static boolean setRightPushAll(String key, List list, long time) {
        if (key.contains(StrUtil.SPACE)) {
            throw new YamiShopBindException(ResponseEnum.EXCEPTION);
        }
        try {
            if (time > 0) {
                redisTemplate.opsForList().rightPushAll(key,list);
                expire(key,time);
            }
            else {
                redisTemplate.opsForList().rightPushAll(key,list);
            }
            return true;
        }
        catch (Exception e) {
            logger.error("Redis opsForList error: {}", e.getMessage());
            return false;
        }
    }
    /**
     * 获取list缓存的size
     * @param key 键
     * @return true成功 false 失败
     */
    public static Long getListSize(String key) {
        if (key.contains(StrUtil.SPACE)) {
            throw new YamiShopBindException(ResponseEnum.EXCEPTION);
        }
        try {
            return redisTemplate.opsForList().size(key);
        }
        catch (Exception e) {
            logger.error("Redis opsForList error: {}", e.getMessage());
            return 0L;
        }
    }
    /**
     * 根据key 获取list指定范围的内容
     * @param key 键 不能为null
     * @param start
     * @param end
     * @return 时间(秒) 返回-1代表为永久有效 失效时间为0,说明该主键未设置失效时间(失效时间默认为-1)
     */
    public static List getListRange(String key, Long start, Long end) {
        if (key.contains(StrUtil.SPACE)) {
            throw new YamiShopBindException(ResponseEnum.EXCEPTION);
        }
        return redisTemplate.opsForList().range(key, start, end);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/SimpleCaptcha.java
New file
@@ -0,0 +1,87 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.util.RandomUtil;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.concurrent.ThreadLocalRandom;
/**
 * 二维码
 * @author yami
 */
public class SimpleCaptcha extends LineCaptcha{
    private static final long serialVersionUID = -9042552338521307038L;
    private static final String CAPTCHA_CODE = "abcdefhjkmnpqrstuvwxyz2345678";
    private int codeCount;
    public SimpleCaptcha(int width, int height, int codeCount, int interfereCount) {
        super(width, height, codeCount, interfereCount);
        this.codeCount = codeCount;
    }
    @Override
    protected void generateCode() {
        this.code = RandomUtil.randomString(CAPTCHA_CODE,codeCount);
    }
    @Override
    public Image createImage(String code) {
        // 图像buffer
        final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        final ThreadLocalRandom random = RandomUtil.getRandom();
        final Graphics2D g = ImgUtil.createGraphics(image, new Color(255,255,255));
        // 干扰线
        drawInterfere(g, random);
        // 创建字体
        g.setFont(this.font);
        final FontMetrics metrics = g.getFontMetrics();
        int minY = metrics.getAscent() - metrics.getLeading() - metrics.getDescent();
        // 文字
        final int len = codeCount;
        int charWidth = width / len;
        for (int i = 0; i < len; i++) {
            // 产生随机的颜色值,让输出的每个字符的颜色值都将不同。
            g.setColor(ImgUtil.randomColor(random));
            g.drawString(String.valueOf(code.charAt(i)), i * charWidth, RandomUtil.randomInt(minY, this.height));
        }
        return image;
    }
    /**
     * 绘制干扰线
     *
     * @param g {@link Graphics2D}画笔
     * @param random 随机对象
     */
    private void drawInterfere(Graphics2D g, ThreadLocalRandom random) {
        // 干扰线
        for (int i = 0; i < this.interfereCount; i++) {
            int xs = random.nextInt(width);
            int ys = random.nextInt(height);
            int xe = xs + random.nextInt(width / 8);
            int ye = ys + random.nextInt(height / 8);
            g.setColor(ImgUtil.randomColor(random));
            g.drawLine(xs, ys, xe, ye);
        }
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/SpelUtil.java
New file
@@ -0,0 +1,58 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import java.lang.reflect.Method;
/**
 * 解析SPEL 表达式
 * @author huxingnan
 * @date 2018/5/21 10:51
 */
public class SpelUtil {
    /**
     * 支持 #p0 参数索引的表达式解析
     * @param rootObject 根对象,method 所在的对象
     * @param spel 表达式
     * @param method ,目标方法
     * @param args 方法入参
     * @return 解析后的字符串
     */
    public static String parse(Object rootObject,String spel, Method method, Object[] args) {
        if (StrUtil.isBlank(spel)) {
            return StrUtil.EMPTY;
        }
        //获取被拦截方法参数名列表(使用Spring支持类库)
        LocalVariableTableParameterNameDiscoverer u =
                new LocalVariableTableParameterNameDiscoverer();
        String[] paraNameArr = u.getParameterNames(method);
        if (ArrayUtil.isEmpty(paraNameArr)) {
            return spel;
        }
        //使用SPEL进行key的解析
        ExpressionParser parser = new SpelExpressionParser();
        //SPEL上下文
        StandardEvaluationContext context = new MethodBasedEvaluationContext(rootObject,method,args,u);
        //把方法参数放入SPEL上下文中
        for (int i = 0; i < paraNameArr.length; i++) {
            context.setVariable(paraNameArr[i], args[i]);
        }
        return parser.parseExpression(spel).getValue(context, String.class);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/SpringContextUtils.java
New file
@@ -0,0 +1,54 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
 * Spring Context 工具类
 * @author lgh
 */
@Component
public class SpringContextUtils implements ApplicationContextAware {
    public static ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        SpringContextUtils.applicationContext = applicationContext;
    }
    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }
    public static <T> T getBean(Class<T> requiredType) {
        return applicationContext.getBean(requiredType);
    }
    public static <T> T getBean(String name, Class<T> requiredType) {
        return applicationContext.getBean(name, requiredType);
    }
    public static boolean containsBean(String name) {
        return applicationContext.containsBean(name);
    }
    public static boolean isSingleton(String name) {
        return applicationContext.isSingleton(name);
    }
    public static Class<? extends Object> getType(String name) {
        return applicationContext.getType(name);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/WordUtil.java
New file
@@ -0,0 +1,266 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import cn.hutool.core.util.ObjectUtil;
import com.aspose.words.Document;
import com.aspose.words.SaveFormat;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.springframework.stereotype.Component;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
 * 进制转换工具,最大支持十进制和DICT.length()进制的转换
 * 1、将十进制的数字转换为指定进制的字符串;
 * 2、将其它进制的数字(字符串形式)转换为十进制的数字
 * @author xuliugen
 * @date 2018/04/23
 */
@Component
public class WordUtil {
    // 标识忽略
    static final int ignoreTg = 0;
    // 标识已读取到'$'字符
    static final int startTg = 1;
    // 标识已读取到'{'字符
    static final int readTg = 2;
    /**
     * 占位符
     * @param
     * @return
     */
    public static void replacePlaceholders(XWPFDocument doc, Map<String, String> params) {
        // 遍历文档中的所有段落
        for (XWPFParagraph para : doc.getParagraphs()) {
            List<XWPFRun> runs = para.getRuns();
            for (int i = 0; i < runs.size(); i++) {
                XWPFRun run = runs.get(i);
                String text = run.getText(run.getTextPosition());
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    if (text != null && text.contains(entry.getKey())) {
                        run.setText(text.replace(entry.getKey(), entry.getValue()), 0);
                    }
                }
            }
        }
    }
    /**
     * 获取表格中占位符信息
     *
     * @param doc               当前文档
     * @param list              存储占位符信息
     * @param placeholderValues 需要替换的值
     * @return void
     * @author liuchao
     * @date 2020/7/6
     */
    public static void getTableParagraphs(XWPFDocument doc, List<XWPFParagraph> list, Map<String, String> placeholderValues) {
        List<XWPFTable> tables = doc.getTables();
        if (ObjectUtil.isEmpty(tables)) {
            return;
        }
        tables.forEach(table -> table.getRows().forEach(row -> row.getTableCells().forEach(cell -> {
            String text = cell.getText();
            if (ObjectUtil.isEmpty(text)) {
                return;
            }
            Iterator<String> it = placeholderValues.keySet().iterator();
            while (it.hasNext()) {
                String key = it.next();
                if (text.indexOf(key) != -1) {
                    list.addAll(cell.getParagraphs());
                }
            }
        })));
    }
    /**
     * 清除占位符信息
     *
     * @param placeholderList 占位符位置信息
     * @param paragraphList   行数据
     * @return void
     * @author liuchao
     * @date 2020/6/10
     */
    public static void clearPlaceholder(List<int[]> placeholderList, List<XWPFParagraph> paragraphList) {
        if (ObjectUtil.isEmpty(placeholderList)) {
            return;
        }
        int[] currentPlaceholder = placeholderList.get(0);
        StringBuilder tempSb = new StringBuilder();
        for (int i = 0; i < paragraphList.size(); i++) {
            XWPFParagraph p = paragraphList.get(i);
            List<XWPFRun> runs = p.getRuns();
            for (int j = 0; j < runs.size(); j++) {
                XWPFRun run = runs.get(j);
                String text = run.getText(run.getTextPosition());
                StringBuilder nval = new StringBuilder();
                char[] textChars = text.toCharArray();
                for (int m = 0; m < textChars.length; m++) {
                    char c = textChars[m];
                    if (null == currentPlaceholder) {
                        nval.append(c);
                        continue;
                    }
                    // 排除'$'和'}'两个字符之间的字符
                    int start = currentPlaceholder[0] * 1000000 + currentPlaceholder[1] * 500 + currentPlaceholder[2];
                    int end = currentPlaceholder[3] * 1000000 + currentPlaceholder[4] * 500 + currentPlaceholder[5];
                    int cur = i * 1000000 + j * 500 + m;
                    if (!(cur >= start && cur <= end)) {
                        nval.append(c);
                    } else {
                        tempSb.append(c);
                    }
                    //判断是否是占位符结尾,如果是那获取新的占位符
                    if (tempSb.toString().endsWith("}")) {
                        placeholderList.remove(0);
                        if (ObjectUtil.isEmpty(placeholderList)) {
                            currentPlaceholder = null;
                            continue;
                        }
                        currentPlaceholder = placeholderList.get(0);
                        tempSb = new StringBuilder();
                    }
                }
                run.setText(nval.toString(), run.getTextPosition());
            }
        }
    }
    /**
     * 获取占位符信息,并且在占位符后面填充值
     *
     * @param paragraphList 行数据
     * @param map           要替换的占位符key\value
     * @return java.util.List<int [ ]>
     * @author liuchao
     * @date 2020/6/10
     */
    public static List<int[]> getPlaceholderList(List<XWPFParagraph> paragraphList, Map<String, String> map) {
        // 存储占位符 位置信息集合
        List<int[]> placeholderList = new ArrayList<>();
        // 当前占位符 0:'$'字符在XWPFParagraph集合中下标
        //          1:'$'字符在XWPFRun集合中下标
        //          2:'$'字符在text.toCharArray()数组下标
        //          3: '}'字符在XWPFParagraph集合中下标
        //          4: '}'字符在XWPFRun集合中下标
        //          5:'}'字符在text.toCharArray()数组下标
        int[] currentPlaceholder = new int[6];
        // 当前标识
        int modeTg = ignoreTg;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < paragraphList.size(); i++) {
            XWPFParagraph p = paragraphList.get(i);
            List<XWPFRun> runs = p.getRuns();
            for (int j = 0; j < runs.size(); j++) {
                XWPFRun run = runs.get(j);
                String text = run.getText(run.getTextPosition());
                if(null == text){
                    text = "";
                }
                char[] textChars = text.toCharArray();
                String newVal = "";
                StringBuilder textSofar = new StringBuilder();
                for (int m = 0; m < textChars.length; m++) {
                    char c = textChars[m];
                    textSofar.append(c);
                    switch (c) {
                        case '$': {
                            modeTg = startTg;
                            sb.append(c);
                        }
                        break;
                        case '{': {
                            if (modeTg == startTg) {
                                sb.append(c);
                                modeTg = readTg;
                                currentPlaceholder[0] = i;
                                currentPlaceholder[1] = j;
                                currentPlaceholder[2] = m - 1;
                            } else {
                                if (modeTg == readTg) {
                                    sb = new StringBuilder();
                                    modeTg = ignoreTg;
                                }
                            }
                        }
                        break;
                        case '}': {
                            if (modeTg == readTg) {
                                modeTg = ignoreTg;
                                sb.append(c);
                                String val = map.get(sb.toString());
                                if (ObjectUtil.isNotEmpty(val)) {
                                    newVal += textSofar.toString() + val;
                                    placeholderList.add(currentPlaceholder);
                                    textSofar = new StringBuilder();
                                }
                                currentPlaceholder[3] = i;
                                currentPlaceholder[4] = j;
                                currentPlaceholder[5] = m;
                                currentPlaceholder = new int[6];
                                sb = new StringBuilder();
                            } else if (modeTg == startTg) {
                                modeTg = ignoreTg;
                                sb = new StringBuilder();
                            }
                        }
                        default: {
                            if (modeTg == readTg) {
                                sb.append(c);
                            } else if (modeTg == startTg) {
                                modeTg = ignoreTg;
                                sb = new StringBuilder();
                            }
                        }
                    }
                }
                newVal += textSofar.toString();
                run.setTextPosition(0);
                run.setText(newVal, run.getTextPosition());
            }
        }
        return placeholderList;
    }
    /**
     * word文档转PDF
     * @param wordPath word文档路径
     * @param outPdfPath PDF输出路径
     */
    public static void wordConvertPdf(String wordPath, String outPdfPath) {
        try(
                FileInputStream fileInputStream = new FileInputStream(wordPath);
                FileOutputStream pdfOutStremp = new FileOutputStream(outPdfPath);
        ) {
            Document document = new Document(fileInputStream);
            document.save(pdfOutStremp, SaveFormat.PDF);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/util/WriteOffCodeUtil.java
New file
@@ -0,0 +1,58 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.util;
import cn.hutool.core.util.StrUtil;
import org.springframework.stereotype.Component;
import java.util.Calendar;
/**
 * 获取核销码的工具方法
 * @author lhd
 * @date 2021/10/26
 */
@Component
public class WriteOffCodeUtil {
    private static final Integer LENGTH = 8;
    private static final Integer ROUND_LENGTH = (LENGTH-2)/2;
    private static final Long INIT_ROUND = 10000000000L;
    /**
     *  随机码: 三位随机数 + (月+日+45) + 三位随机数
     *  若随机码不够用,可更改长度:LENGTH 和 初始值:INIT_ROUND,增加随机码
     * @param oldCode
     * @return
     */
    public static String getCode(String oldCode){
        Calendar cal = Calendar.getInstance();
        int dayAddMonth = (cal.get(Calendar.DATE)) + cal.get(Calendar.MONTH) + 46;
        String code;
        Long roundNum;
        if (StrUtil.isNotBlank(oldCode)){
            //随机数增加的最大值
            long changeNum = 5L;
            // 获取随机数
            long num = Long.parseLong(oldCode.substring(0,ROUND_LENGTH) + oldCode.substring(LENGTH - ROUND_LENGTH));
            roundNum = num + Math.round(Math.random() * changeNum) + 1;
        }else {
            // 随机数 = 5*1000000000011以内的随机数 + 2*1000000000011
            roundNum = Math.round(Math.random() * 5 * INIT_ROUND) + 2 * INIT_ROUND;
        }
        // 随机数大于等于最大值,初始化
        long maxRoundNum= 10L * INIT_ROUND;
        if (roundNum >= maxRoundNum){
            roundNum =  roundNum - maxRoundNum + INIT_ROUND;
        }
        code = roundNum.toString();
        return code.substring(0,ROUND_LENGTH)+ dayAddMonth + code.substring(ROUND_LENGTH);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/wrapper/RequestWrapper.java
New file
@@ -0,0 +1,102 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wrapper;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
 * @author Citrus
 * @date 2021/8/13 13:31
 */
@Slf4j
public class RequestWrapper extends HttpServletRequestWrapper {
    private String body;
    /**
     * Constructs a request object wrapping the given request.
     *
     * @param request The request to wrap
     * @throws IllegalArgumentException if the request is null
     */
    public RequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        try {
            InputStream inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[1024];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                stringBuilder.append("");
            }
        } catch (IOException e) {
            log.error("IOException:", e);
        } finally {
            if (bufferedReader != null) {
                bufferedReader.close();
            }
        }
        body = stringBuilder.toString();
    }
    public String getBody() {
        return body;
    }
    public void setBody(String body) {
        this.body = body;
    }
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }
    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }
            @Override
            public boolean isReady() {
                return false;
            }
            @Override
            public void setReadListener(ReadListener readListener) {
            }
            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
        };
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/wrapper/ResponseWrapper.java
New file
@@ -0,0 +1,77 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wrapper;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Objects;
/**
 * 返回值输出代理类
 * @author Citrus
 * @date 2021/8/11 14:09
 */
public class ResponseWrapper extends HttpServletResponseWrapper {
    private final ByteArrayOutputStream buffer;
    private final ServletOutputStream outputStream;
    public ResponseWrapper(HttpServletResponse response) {
        super(response);
        buffer = new ByteArrayOutputStream();
        outputStream = new WrapperOutPutStream(buffer);
    }
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return outputStream;
    }
    @Override
    public void flushBuffer() throws IOException {
        if (Objects.nonNull(outputStream)) {
            outputStream.flush();
        }
    }
    public byte[] getContent() throws IOException{
        flushBuffer();
        return buffer.toByteArray();
    }
    static class WrapperOutPutStream extends ServletOutputStream {
        private final ByteArrayOutputStream bos;
        public WrapperOutPutStream(ByteArrayOutputStream bos) {
            this.bos = bos;
        }
        @Override
        public boolean isReady() {
            return false;
        }
        @Override
        public void setWriteListener(WriteListener writeListener) {
        }
        @Override
        public void write(int b) throws IOException {
            bos.write(b);
        }
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/WxInterfaceUtil.java
New file
@@ -0,0 +1,334 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.response.WxLiveProdResponse;
import com.yami.shop.common.response.WxServerResponse;
import com.yami.shop.common.util.Json;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.common.wx.bean.*;
import com.yami.shop.common.wx.bean.resp.GoodsInfoRespParam;
import com.yami.shop.common.wx.bean.resp.GoodsListRespParam;
import com.yami.shop.common.wx.bean.resp.RoomDetailResponse;
import com.yami.shop.common.wx.bean.resp.RoomResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.*;
/**
 * 微信相关工具类
 * @author LHD
 */
@Slf4j
@Component
public class WxInterfaceUtil {
    private String url;
    private String wxImgUrl = "https://api.weixin.qq.com/cgi-bin/media";
    private String liveUrl = "https://api.weixin.qq.com";
    private String goodsUrl = "https://api.weixin.qq.com/wxaapi/broadcast/goods";
    private String goodsStatusUrl = "https://api.weixin.qq.com/wxa/business";
    private String goodsListUrl = "https://api.weixin.qq.com/wxaapi/broadcast/goods/getapproved?access_token=[ACCESS_TOKEN]";
    public static String GET_GOODS_WARE_HOUSE = "getgoodswarehouse";
    public static String GET_APPROVED = "getapproved";
    public static String ERR_MSG = "errmsg";
//    /**
//     * 上传临时素材接口
//     * @return
//     */
//    public ServerResponse<ImageResponse> uploadMedia(WxInterfaceInfo creditInfo){
//        Map<String, Object> requestParam = new HashMap<>(16);
////        requestParam.put("type", creditInfo.getType());
//        // 微信token
////        requestParam.put("access_token", creditInfo.getAccessToken());
//        requestParam.put("media", creditInfo.getByteArray());
//
//        return signAndSend(creditInfo, requestParam,new TypeReference<ServerResponse<ImageResponse>>() {});
//
//    }
    /**
     * 增加直播间接口
     * @return
     */
    public WxServerResponse<Void> addLiveRoom(WxLiveRoomInfo wxLiveRoomInfo){
        Map<String, Object> requestParam = new HashMap<>(16);
        requestParam.put("name",wxLiveRoomInfo.getName());
        requestParam.put("coverImg",wxLiveRoomInfo.getCoverImgId());
        requestParam.put("startTime",wxLiveRoomInfo.getWxStartTime());
        requestParam.put("endTime",wxLiveRoomInfo.getWxEndTime());
        requestParam.put("anchorName",wxLiveRoomInfo.getAnchorName());
        requestParam.put("anchorWechat",wxLiveRoomInfo.getAnchorWechat());
        requestParam.put("shareImg",wxLiveRoomInfo.getShareImgId());
        requestParam.put("feedsImg",wxLiveRoomInfo.getFeedsImgId());
        requestParam.put("isFeedPublic",wxLiveRoomInfo.getIsFeedsPublic());
        requestParam.put("type",wxLiveRoomInfo.getType());
        requestParam.put("screenType",wxLiveRoomInfo.getScreenType());
        requestParam.put("closeLike",wxLiveRoomInfo.getCloseLike());
        requestParam.put("closeGoods",wxLiveRoomInfo.getCloseGoods());
        requestParam.put("closeComment",wxLiveRoomInfo.getCloseComment());
        requestParam.put("closeReplay",wxLiveRoomInfo.getCloseReplay());
        requestParam.put("closeShare",wxLiveRoomInfo.getCloseShare());
        requestParam.put("closeKf",wxLiveRoomInfo.getCloseKf());
        return signAndSend(wxLiveRoomInfo, requestParam,new TypeReference<WxServerResponse<Void>>() {});
    }
    /**
     * 获取直播间列表接口
     * @return
     */
    public WxServerResponse<List<RoomDetailResponse>> pageLiveRoom(PageLiveRoomInfo wxLiveRoomInfo){
        Map<String, Object> requestParam = new HashMap<>(16);
        requestParam.put("start",wxLiveRoomInfo.getStart());
        requestParam.put("limit", wxLiveRoomInfo.getLimit());
        return signAndSend(wxLiveRoomInfo, requestParam,new TypeReference<WxServerResponse<List<RoomDetailResponse>>>() {});
    }
    /**
     * 4.直播间导入商品
     * 调用接口往指定直播间导入已入库的商品
     * @return
     */
    public WxServerResponse<Void> addLiveRoomProds(WxRoomProdInfo wxRoomProdInfo){
        Map<String, Object> requestParam = new HashMap<>(16);
        requestParam.put("ids",wxRoomProdInfo.getIds());
        requestParam.put("roomId",wxRoomProdInfo.getRoomId());
        return signAndSend(wxRoomProdInfo, requestParam,new TypeReference<WxServerResponse<Void>>() {});
    }
    /**
     * 查询直播间回放
     * @return
     */
    public WxServerResponse<PageParam<RoomResponse>> pagePlayBackByRoomId(PageLiveRoomInfo wxRoomPlayBackInfo){
        Map<String, Object> requestParam = new HashMap<>(16);
        requestParam.put("action","get_replay");
        requestParam.put("room_id",wxRoomPlayBackInfo.getRoomId());
        requestParam.put("start",wxRoomPlayBackInfo.getStart());
        requestParam.put("limit",wxRoomPlayBackInfo.getLimit());
        return signAndSend(wxRoomPlayBackInfo, requestParam,new TypeReference<WxServerResponse<PageParam<RoomResponse>>>() {});
    }
//    /**
//     * 发送请求,获取响应结果
//     * @param requestParam
//     * @return
//     */
//    private <T> ServerResponse<T> signAndSend(WxInterfaceInfo creditInfo, Map<String, Object> requestParam, TypeReference<ServerResponse<T>> typeReference) {
////        log.info(Json.toJsonString(requestParam));
//        String uploadMediaUrl = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";
//        uploadMediaUrl = uploadMediaUrl.replace("ACCESS_TOKEN", creditInfo.getAccessToken()).replace("TYPE", creditInfo.getType());
//        System.out.println(uploadMediaUrl);
//        String body = HttpUtil.createPost(uploadMediaUrl)
//                .contentType("multipart/form-data;boundary=----WebKitFormBoundaryLFoM36YJSszHqhMR")
//                .form(Json.toJsonString(requestParam))
//                .execute().body();
////        String body = HttpUtil.createPost(wxImgUrl + creditInfo.getRequestUrl()).form(requestParam).contentType("application/x-www-form-urlencoded").execute().body();
//        log.info(body);
//        return JSON.parseObject(body, typeReference);
//    }
    /**
     * 商品添加并提审
     * 商品添加到微信并且提交审核的接口
     */
    public GoodsInfoRespParam prodAddVerify(GoodsInfoReqParam goodsInfo){
        Map<String, Object> requestParam = new HashMap<>(16);
        requestParam.put("goodsInfo",goodsInfo);
        GoodsInfoRespParam goodsInfoRespParam = prodSignAndSend(goodsInfo, requestParam, new TypeReference<GoodsInfoRespParam>() {});
        System.out.println("goodsInfo: " + goodsInfoRespParam);
        if (!Objects.equals(goodsInfoRespParam.getErrcode(),0) ) {
            // 提交审核失败
            throw new YamiShopBindException("yami.examine.fail");
        }
        return goodsInfoRespParam;
    }
//    /**
//     * 撤回审核
//     * 可撤回直播商品的提审申请,消耗的提审次数不返还
//     */
//    public GoodsInfoRespParam prodCancelVerify(GoodsReqInfo goodsInfo){
//        Map<String, Object> requestParam = new HashMap<>(16);
//        requestParam.put("auditId",goodsInfo.getAuditId());
//        requestParam.put("goodsId",goodsInfo.getGoodsId());
//        goodsInfo.setRequestUrl("/resetaudit?access_token=");
//        GoodsInfoRespParam goodsRespInfo = prodSignAndSend(goodsInfo, requestParam, new TypeReference<GoodsInfoRespParam>() {});
//        if (!Objects.equals(goodsRespInfo.getErrcode(),0) ) {
//            throw new YamiShopBindExcetion("撤回审核失败");
//        }
//        return goodsRespInfo;
//    }
//    /**
//     * 重新提交审核
//     * 调用此接口可以对已撤回提审的商品再次发起提审申请
//     * 需要更新 "auditId": 525022184
//     */
//    public GoodsInfoRespParam prodAgainVerify(GoodsReqInfo goodsInfo){
//        Map<String, Object> requestParam = new HashMap<>(16);
//        requestParam.put("goodsId",goodsInfo.getGoodsId());
//        goodsInfo.setRequestUrl("/audit?access_token=");
//        GoodsInfoRespParam goodsRespInfo = prodSignAndSend(goodsInfo, requestParam, new TypeReference<GoodsInfoRespParam>() {});
//        if (!Objects.equals(goodsRespInfo.getErrcode(),0) ) {
//            throw new YamiShopBindExcetion("重新提交审核失败");
//        }
//        return goodsRespInfo;
//    }
    /**
     * 调用此接口,可删除【小程序直播】商品库中的商品,删除后直播间上架的该商品也将被同步删除,不可恢复
     * 删除商品
     * {
     *     "errcode": 0,
     * }
     */
    public WxLiveProdResponse<Void> prodDelete(GoodsReqInfo goodsInfo){
        Map<String, Object> requestParam = new HashMap<>(16);
        requestParam.put("goodsId",goodsInfo.getGoodsId());
        goodsInfo.setRequestUrl("/wxaapi/broadcast/goods/delete?access_token=");
        return liveProdSignAndSend(goodsInfo, requestParam, new TypeReference<WxLiveProdResponse<Void>>() {});
    }
    /**
     * 调用此接口可以更新商品信息,审核通过的商品仅允许更新价格类型与价格,审核中的商品不允许更新,
     * 未审核的商品允许更新所有字段, 只传入需要更新的字段
     * 更新商品
     * {
     *     "errcode": 0,
     * }
     */
    public WxLiveProdResponse<Void> prodUpdate(UpdateGoodsInfoReqParam goodsInfo){
        Map<String, Object> requestParam = new HashMap<>(16);
        requestParam.put("goodsInfo",goodsInfo);
        return liveProdSignAndSend(goodsInfo, requestParam, new TypeReference<WxLiveProdResponse<Void>>() {});
    }
    /**
     * 获取商品状态 调用此接口可获取商品的信息与审核状态
     * {
     *     "errcode": 0,
     * }
     */
    public WxLiveProdResponse<List<GoodsInfoRespParam>> prodGetStatus(GoodsReqInfo goodsInfo){
        Map<String, Object> requestParam = new HashMap<>(16);
        if (CollectionUtils.isEmpty(goodsInfo.getGoodsIds())) {
            List<Long> list = new ArrayList<>();
            list.add(goodsInfo.getGoodsId());
            requestParam.put("goods_ids", list.toArray());
        } else {
            requestParam.put("goods_ids", goodsInfo.getGoodsIds().toArray());
        }
        goodsInfo.setRequestUrl("/wxa/business/getgoodswarehouse?access_token=");
        return liveProdSignAndSend(goodsInfo, requestParam, new TypeReference<WxLiveProdResponse<List<GoodsInfoRespParam>>>() {});
    }
    /**
     * 获取商品列表 调用此接口可获取商品的信息与审核状态
     * 调用此接口可获取商品列表
     * {
     *     "errcode": 0,
     * }
     */
    public GoodsListRespParam prodList(GoodsListReqParam goodsInfo){
        Map<String, Object> requestParam = new HashMap<>(16);
        requestParam.put("offset", goodsInfo.getOffset());
        requestParam.put("limit", goodsInfo.getLimit());
        requestParam.put("status", goodsInfo.getStatus());
        GoodsListRespParam goodsRespInfo = prodSignAndSend(goodsInfo, requestParam, new TypeReference<GoodsListRespParam>() {});
        if (!Objects.equals(goodsRespInfo.getErrcode(),0) ) {
            // 获取商品列表失败
            throw new YamiShopBindException("yami.get.goods");
        }
        return goodsRespInfo;
    }
    /**
     *  微信请求-商品管理请求
     *
     */
    private <T> T prodSignAndSend(WxInterfaceInfo wxInterfaceInfo, Map<String, Object> requestParam, TypeReference<T> typeReference) {
        log.info(Json.toJsonString(requestParam));
        String reqUrl = goodsUrl +  wxInterfaceInfo.getRequestUrl() + wxInterfaceInfo.getAccessToken();
        if (wxInterfaceInfo.getRequestUrl().contains(GET_GOODS_WARE_HOUSE)) {
            reqUrl = goodsStatusUrl +  wxInterfaceInfo.getRequestUrl() + wxInterfaceInfo.getAccessToken();
        }
        if (wxInterfaceInfo.getRequestUrl().contains(GET_APPROVED)) {
            reqUrl = goodsListUrl.replace("ACCESS_TOKEN",wxInterfaceInfo.getAccessToken());
        }
        log.info("url: " + reqUrl);
        String body = HttpUtil.createPost(reqUrl)
                .body(Json.toJsonString(requestParam))
                .contentType("application/json")
                .execute().body();
        log.info(body);
        if (StringUtils.contains(body,ERR_MSG)) {
            if(StringUtils.contains(body, "300018")){
                throw new YamiShopBindException("商品图片尺寸过大");
            }
            String message = I18nMessage.getMessage("yami.request.error");
            throw new YamiShopBindException(message+body);
        }
        return JSON.parseObject(body,typeReference);
    }
    /**
     *  微信请求-统一直播间接口处理
     */
    private <T> WxServerResponse<T> signAndSend(WxInterfaceInfo wxInterfaceInfo, Map<String, Object> requestParam, TypeReference<WxServerResponse<T>> typeReference) {
        log.info(Json.toJsonString(requestParam));
        String str = liveUrl +  wxInterfaceInfo.getRequestUrl() + wxInterfaceInfo.getAccessToken();
        System.out.println("str: " + str);
        String body = HttpUtil.createPost(str)
                .body(Json.toJsonString(requestParam))
                .contentType("application/json")
                .execute().body();
        log.info(body);
        return JSON.parseObject(body, typeReference);
    }
    /**
     *  微信请求-统一直播商品处理
     */
    private <T> WxLiveProdResponse<T> liveProdSignAndSend(WxInterfaceInfo wxInterfaceInfo, Map<String, Object> requestParam, TypeReference<WxLiveProdResponse<T>> typeReference) {
        log.info(Json.toJsonString(requestParam));
        String str = liveUrl +  wxInterfaceInfo.getRequestUrl() + wxInterfaceInfo.getAccessToken();
        System.out.println("str: " + str);
        String body;
        try {
            body = HttpUtil.createPost(str)
                    .contentType("application/json")
                    .body(Json.toJsonString(requestParam))
                    .execute().body();
        }catch (Exception e){
            // 远程微信连接异常!
            throw new YamiShopBindException("yami.network.exception");
        }
        log.info(body);
        return JSON.parseObject(body, typeReference);
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/GoodsInfoReqParam.java
New file
@@ -0,0 +1,44 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean;
import lombok.Data;
/**
 * 微信小程序直播请求参数
 * @author yami
 */
@Data
public class GoodsInfoReqParam extends WxInterfaceInfo{
    private String coverImgUrl;
    private String name;
    private Integer priceType;
    private Double price;
    private Double price2;
    private String url;
    private String requestUrl;
    /**
     *  微信商品id
     */
    private Long goodsId;
    @Override
    public String getRequestUrl() {
        return "/add?access_token=";
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/GoodsListReqParam.java
New file
@@ -0,0 +1,31 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean;
import lombok.Data;
/**
 * 微信小程序直播参数
 * @author yami
 */
@Data
public class GoodsListReqParam extends WxInterfaceInfo{
    private Long offset;
    private Long limit;
    private Integer status;
    @Override
    public String getRequestUrl() {
        return "/getapproved?access_token=";
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/GoodsReqInfo.java
New file
@@ -0,0 +1,44 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean;
import lombok.Data;
import java.util.List;
/**
 * 微信小程序直播参数
 * @author yami
 */
@Data
public class GoodsReqInfo extends WxInterfaceInfo{
    /**
     *     商品ID
     */
    private Long goodsId;
    private List<Long> goodsIds;
    /**
     * 审核单ID
     */
    private Long auditId;
    private String requestUrl;
    @Override
    public String getRequestUrl() {
        return requestUrl;
    }
    public void setRequestUrl(String requestUrl) {
        this.requestUrl = requestUrl;
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/ImageUploadReqParam.java
New file
@@ -0,0 +1,29 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean;
import lombok.Data;
/**
 * 图片请求参数
 * @author yami
 */
@Data
public class ImageUploadReqParam {
    private String name;
    private String type = "image/jpeg";
    private Integer size;
    private byte[] file;
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/LiveUserReqInfo.java
New file
@@ -0,0 +1,29 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean;
import lombok.Data;
/**
 * 直播用户请求参数
 * @author yami
 */
@Data
public class LiveUserReqInfo extends WxInterfaceInfo{
    /**
     * 主播微信号
     */
    private String username;
    /**
     * 角色列表
     */
    private Integer role;
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/PageLiveRoomInfo.java
New file
@@ -0,0 +1,28 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean;
import lombok.Data;
/**
 * 微信直播间接口所需参数
 * @author LHD
 */
@Data
public class PageLiveRoomInfo extends WxInterfaceInfo{
    private Long roomId;
    @Override
    public String getRequestUrl() {
        return "/wxa/business/getliveinfo?access_token=";
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/UpdateGoodsInfoReqParam.java
New file
@@ -0,0 +1,45 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean;
import lombok.Data;
/**
 * 修改直播间商品请求参数
 * @author yami
 */
@Data
public class UpdateGoodsInfoReqParam extends WxInterfaceInfo{
    private String coverImgUrl;
    private String name;
    private Integer priceType;
    private Double price;
    private Double price2;
    private String url;
    private String requestUrl;
    /**
     *  微信商品id
     */
    private Long goodsId;
    @Override
    public String getRequestUrl() {
        return "/wxaapi/broadcast/goods/update?access_token=";
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/WxInterfaceInfo.java
New file
@@ -0,0 +1,46 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean;
import lombok.Data;
import org.apache.http.entity.mime.content.ByteArrayBody;
/**
 * 微信接口所需参数
 * @author LHD
 */
@Data
public class WxInterfaceInfo {
    /**
     * 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb)
     */
    private String imgType = "image";
    /**
     * 微信的accessToken
     */
    private String accessToken;
    /**
     * 图片字节数组
     */
    private byte[] bytes;
    private Long limit;
    private Long start;
    private ByteArrayBody byteArray;
    public String getRequestUrl() {
        return "/upload";
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/WxLiveRoomInfo.java
New file
@@ -0,0 +1,114 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean;
import lombok.Data;
/**
 * 微信直播间接口所需参数
 * @author LHD
 */
@Data
public class WxLiveRoomInfo extends WxInterfaceInfo{
    /**
     * 直播间名称
     */
    private String name;
    /**
     * 主播昵称
     */
    private String anchorName;
    /**
     * 主播微信号
     */
    private String anchorWechat;
    /**
     * 背景图
     */
    private String coverImg;
    /**
     * 主播分享图
     */
    private String shareImg;
    /**
     * 购物直播频道封面图
     */
    private String feedsImg;
    /**
     * 是否开启官方收录
     */
    private Integer isFeedsPublic;
    /**
     * 直播间类型 1.推流 2.手机直播
     */
    private Integer type;
    /**
     * 0.竖屏 1.横屏
     */
    private Integer screenType;
    /**
     * 直播间功能
     */
    private String roomTools;
    /**
     * 购物直播频道封面图微信mediaId
     */
    private String feedsImgId;
    /**
     * 购物直播频道封面图微信mediaId
     */
    private String coverImgId;
    /**
     * 购物直播频道封面图微信mediaId
     */
    private String shareImgId;
    /**
     * 直播开始时间
     */
    private Long wxStartTime;
    /**
     * 直播结束时间
     */
    private Long wxEndTime;
    /**
     * 是否关闭客服 0 开启,1 关闭
     */
    private Integer closeKf;
    /**
     * 是否关闭点赞  0 开启,1 关闭
     */
    private Integer closeLike;
    /**
     * 是否关闭货架  0 开启,1 关闭
     */
    private Integer closeGoods;
    /**
     * 是否关闭评论  0 开启,1 关闭
     */
    private Integer closeComment;
    /**
     * 是否关闭回放  0 开启,1 关闭
     */
    private Integer closeReplay;
    /**
     * 是否关闭分享  0 开启,1 关闭
     */
    private Integer closeShare;
    @Override
    public String getRequestUrl() {
        return "/wxaapi/broadcast/room/create?access_token=";
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/WxRoomProdInfo.java
New file
@@ -0,0 +1,32 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean;
import lombok.Data;
import java.util.List;
/**
 * 微信直播间商品详情参数
 * @author yami
 */
@Data
public class WxRoomProdInfo extends WxInterfaceInfo{
    private List<Long> ids;
    private Long roomId;
    @Override
    public String getRequestUrl() {
        return "/wxaapi/broadcast/room/addgoods?access_token=";
    }
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/GoodsInfoRespParam.java
New file
@@ -0,0 +1,72 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean.resp;
import lombok.Data;
/**
 * 微信小程序直播响应参数
 * @author yami
 */
@Data
public class GoodsInfoRespParam {
    /**
     *     商品ID
     *     "goodsId":"5","auditId":430376413,"errcode":0
     *     {"goodsId":"8","auditId":430376427,"errcode":0}
     */
    private Integer goodsId;
    /**
     * 审核单ID
     */
    private Integer auditId;
    /**
     * 商品图片链接
     */
    private String coverImgUrl;
    /**
     * 商品名称
     */
    private String name;
    /**
     * 1:一口价,此时读price字段; 2:价格区间,此时price字段为左边界,price2字段为右边界; 3:折扣价,此时price字段为原价,price2字段为现价;
     */
    private Integer priceType;
    /**
     * 价格左区间,单位“元”
     */
    private Double price;
    /**
     * 价格右区间,单位“元”
     */
    private Double price2;
    /**
     * 商品小程序路径
     */
    private String url;
    /**
     * 1、2:表示是为 API 添加商品,否则是直播控制台添加的商品
     */
    private Integer thirdPartyTag;
    private Integer errcode;
    /**
     * 0:未审核,1:审核中,2:审核通过,3审核失败
     */
    private Integer auditStatus;
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/GoodsListInfosRespParam.java
New file
@@ -0,0 +1,52 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean.resp;
import lombok.Data;
/**
 * 微信小程序直播参数
 * @author yami
 */
@Data
public class GoodsListInfosRespParam {
    /**
     * 商品ID
     */
    private Long goodsId;
    /**
     *     商品图片url
     */
    private String coverImgUrl;
    /**
     * 商品名称
     */
    private String name;
    /**
     * 商品详情页的小程序路径
     */
    private String url;
    /**
     * 1:一口价,此时读price字段; 2:价格区间,此时price字段为左边界,price2字段为右边界; 3:折扣价,此时price字段为原价,price2字段为现价;
     */
    private Integer priceType;
    /**
     * 价格左区间,单位“元”
     */
    private Double price;
    /**
     * 价格右区间,单位“元”
     */
    private Double price2;
    /**
     * 1、2:表示是为 API 添加商品,否则是直播控制台添加的商品
     */
    private Integer thirdPartyTag;
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/GoodsListRespParam.java
New file
@@ -0,0 +1,30 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean.resp;
import lombok.Data;
/**
 * 微信小程序直播参数
 * @author yami
 */
@Data
public class GoodsListRespParam {
    private Long errcode;
    private String errmsg;
    private GoodsListInfosRespParam goods;
    /**
     * 商品个数
     */
    private Integer total;
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/ImageResponse.java
New file
@@ -0,0 +1,29 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean.resp;
import lombok.Data;
/**
 * 注册返回值
 * @author LGH
 */
@Data
public class ImageResponse {
    private String type;
    private String media_id;
    private String created_at;
//    private String[] item;
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/LiveUserRespInfo.java
New file
@@ -0,0 +1,41 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean.resp;
import lombok.Data;
/**
 * 直播用户响应参数
 * @author yami
 */
@Data
public class LiveUserRespInfo{
    /**
     * 主播微信号
     */
    private String username;
    /**
     * 昵称
     */
    private String nickname;
    /**
     * 头像
     */
    private String headingimg;
    /**
     * 角色列表
     */
    private Integer[] roleList;
    /**
     * openId
     */
    private String openid;
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/RoomDetailResponse.java
New file
@@ -0,0 +1,97 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean.resp;
import lombok.Data;
import java.util.List;
/**
 * 注册返回值
 * @author LGH
 */
@Data
public class RoomDetailResponse {
    /**
     * 直播间id
     */
    private Long roomId;
    /**
     * 直播间名称
     */
    private String name;
    /**
     * 主播昵称
     */
    private String anchorName;
    /**
     * 背景图
     */
    private String coverImg;
    /**
     * 主播分享图
     */
    private String shareImg;
    /**
     * 购物直播频道封面图
     */
    private String feedsImg;
    /**
     * 是否开启官方收录
     */
    private Integer isFeedsPublic;
    /**
     * 直播间类型 1.推流 2.手机直播
     */
    private Integer type;
    /**
     * 1.竖屏 2.横屏
     */
    private Integer screenType;
    /**
     * 直播间功能
     */
    private String roomTools;
    /**
     * 购物直播频道封面图微信mediaId
     */
    private String feedsImgId;
    /**
     * 购物直播频道封面图微信mediaId
     */
    private String coverImgId;
    /**
     * 购物直播频道封面图微信mediaId
     */
    private String shareImgId;
    /**
     * 直播开始时间
     */
    private Long wxStartTime;
    /**
     * 直播结束时间
     */
    private Long wxEndTime;
    /**
     * 直播间状态
     */
    private Integer liveStatus;
    /**
     * 直播间商品
     */
    private List<GoodsInfoRespParam> goods;
    /**
     * 直播间商品
     */
    private Integer total;
}
yami-shop-common/src/main/java/com/yami/shop/common/wx/bean/resp/RoomResponse.java
New file
@@ -0,0 +1,27 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.common.wx.bean.resp;
import lombok.Data;
/**
 * 注册返回值
 * @author LGH
 */
@Data
public class RoomResponse {
    private Long roomId;
    private String qrcodeUrl;
    private String createdAt;
}
yami-shop-common/src/main/resources/i18n/messages.properties
yami-shop-common/src/main/resources/i18n/messages_en.properties
New file
@@ -0,0 +1,726 @@
yami.activity.cannot.delete=Cannot delete in the active state
yami.activity.prod.cannot.delete=The activity is in progress. You can not delete the product. You can wait for the activity to finish or after the group activity is invalid
yami.activity.cannot.find=This activity was not found. Please try again later
yami.activity.cannot.find.check=The activity does not exist, has not started or has ended
yami.activity.prod.no.exist=The active product does not exist. Please try again later
yami.activity.prod.status=The activity includes offline products
yami.activity.prod.update.error=Failed to update active product
yami.activity.prod.no.auth=You are not authorized to operate this activity product
yami.activity.no.auth=You are not authorized to operate this activity
yami.activity.add.prod.empty=The product to be added cannot be empty
yami.activity.enable.prod.empty=Failed to enable. Please select at least one active product
yami.activity.disable=Failure to fail, activity not in progress or preheat state cannot fail operation
yami.activity.info.check=Please fill in the full information
yami.activity.item.check=Activity item cannot be empty, there must be at least one active item
yami.activity.status.check=The activity has been offline by the platform. The status cannot be changed
yami.activity.now.over.end.time=The current time has exceeded the end time of the activity. The activity cannot be enabled
yami.distribution.has.distributionUser=The user is already in use, please do not modify it again
yami.discount.MaxReduceAmount.limit=Please enter a number less than 10 trillion
yami.activity.add.success=Added successfully
yami.activity.update.success=Modification succeeded
yami.submitted.successfully=Submitted successfully
yami.submitted.examine=Submitted for review
yami.no.auth=No permission to operate
yami.delete.successfully=Deletion succeeded
yami.undo.successfully=Revocation successful
yami.address.added.successfully=Address added successfully
yami.address.modified.successfully=Address modified successfully
yami.deleted.address.successfully=Address deleted successfully
yami.address.exists=The address already exists
yami.address.add.limit=Shipping address has reached the upper limit, no more new address can be added
yami.address.cannot.delete=The default address cannot be deleted
yami.user.address.delete=The address has been deleted
yami.user.receive.score=Get points successfully
yami.user.receive.score.check=Today has been signed in, please try again tomorrow!
yami.shopCart.enter.num=Enter change quantity
yami.constant.code.expire=QR code expired
yami.network.exception=Network anomaly
yami.network.busy=The server is busy. Please try again later
yami.examine.fail=Failed to submit for review
yami.examine.already=The application has been reviewed
yami.examine.status.error=Audit status error
yami.get.goods=Failed to get product list
yami.request.error=Third party request failed\uFF1A
yami.request.data.too.long=The request data is too long
yami.address.receiver.length.limit=The length of receiver's name is too long
yami.group.team.no.exist=Team information not found
yami.group.order.update.fail=Failed to update the order to be shipped. Please try again later
yami.group.team.no.join=The team is not in the group, can not participate in the group
yami.group.no.progress=The group activity is not in progress. Please try again later
yami.group.prod.status.error=The active product is not in normal state
yami.group.prod.sold.out=The product specifications have been sold out or off the shelf
yami.group.prod.shop.limit=The limited quantity of goods purchased is
yami.group.user.shop.num=, you have purchased
yami.group.user.now.shop=Buy now
yami.group.prod.overstep.shop.limit=,Exceeding the maximum purchase quantity
yami.group.prod.insufficient.stock=Insufficient stock, please reselect purchase quantity
yami.group.prod.has.group.order=You have an order in group purchase, please be patient and wait for the group to be successful.
yami.group.user.join.group=You are participating in this activity, please try again after the success of the group
yami.group.user.join.check=The current order is waiting for the group status, and the next operation can be carried out after waiting for the group
yami.group.user.join.group.error=You have participated in this group. You can't join it again
yami.group.order.no.exist=The order does not exist
yami.request.too.much=The request is too frequent. Please try again later
yami.day=day
yami.constant.num=second
yami.seckill.order.expire=The order has expired. Please reselect the product for seckill
yami.seckill.complete=This round of goods have been killed in seconds, there are still users who have not paid, there are still opportunities
yami.seckill.finish=This product has been killed by seconds. Please come earlier next time
yami.seckill.limit.shop=The second sale of goods is limited
yami.seckill.num=piece
yami.seckill.exception=Seckill activity not started or ended
yami.seckill.not.start=Seckill activity has not started
yami.seckill.has.ended=Seckill activity has ended
yami.seckill.prod=Products cannot participate in the second kill
yami.seckill.input.maxNum=Please enter the purchase limit quantity
yami.seckill.cannot.delete=Seckill activity is not closed, unable to delete
yami.seckill.cannot.invalid=Spike activity has violated the shelf, can not be closed
yami.shop.cart.prod.unrecognized=The shopping cart contains unrecognized items
yami.delivery.address=Please fill in the delivery address
yami.product.remove=Item removed from cart
yami.station.address.check=Please fill in the self provided information
yami.station.detail.check=Please select the pick-up point and fill in the complete self collection information
yami.station.no.find=The bootstrap information was not found
yami.product.not.exist=The product information cannot be found
yami.product.off.not.enable.disProduct=The product are not online, and the distribution product cannot be put on the shelf
yami.product.already.deleted=This product has been removed
yami.stock.no.number=Inventory must be a purely numeric integer, and enter up to 9 digits
yami.product.service.delete=The product status is incorrect, please contact the platform
yami.renovation.not.exist=The decoration information could not be found
yami.unable.get.page=Unable to get page information
yami.product.off.shelves=Product offline
yami.product.disable = The product has been withdrawn or sold out
yami.product.on.normal=The product is not in normal state, modification failed
yami.insufficient.inventory= Insufficient stock, please place a new order
yami.insufficient.inventory.place.new.order= insufficient stock
yami.product=product
yami.selelct.items=Please select the goods you need to add to the shopping cart
yami.product.download=Start downloading templates
yami.product.dvy.type=Please select delivery method
yami.product.dvy.fee=Freight cannot be less than zero
yami.product.group.check=A combined item must be associated with a single item
yami.product.category.not.under=The current platform category is no longer available, please refresh the category list and select again
yami.product.category.not.exit=You have cancelled your contract with this product type, please re-contract this product type to be listed
yami.product.category.is.offline=The platform category has been taken offline and the product cannot be listed
yami.product.shop.category.not.under=The current store category is no longer available, please refresh the category list and select again
yami.product.brand.not.under=The currently selected brand is no longer available, please select again
yami.product.brand.not.delete=Some products are using the brand and cannot be deleted
yami.product.join.group=The product is participating in the group activity. The specification cannot be modified
yami.product.join.seckill=The product is participating in the seckill activity. The specification cannot be modified
yami.product.no.exist=Product information does not exist
yami.product.no.auth=You have no permission to obtain the product specification information
yami.product.no.auth.update=No permission to modify this product
yami.product.category.offline=The platform classification is offline, the product cannot be put on the shelf, please contact the administrator before operation
yami.product.signing.category.invalid=The contract classification of this product has expired, and the status of the product cannot be modified
yami.product.shop.category.offline=This shop category is offline, the product cannot be put on the shelf
yami.product.shop.offline=The store is offline in violation of the rules. This operation cannot be performed. Please contact the administrator and try again
yami.product.shop.AUDIT=The store is reviewing. This operation cannot be performed. Please contact the administrator and try again
yami.product.enable.sku=At least one product specification must be enabled
yami.same.specifications=The same name specification already exists
yami.shop.name.have.already=Already have the same store name
yami.shop.auditing=The store is under review, please do not submit it repeatedly
yami.product.sold.out=Goods sold empty or off the shelf
yami.order.expired=The order has expired. Please order again
yami.add.live.prod.num=Failed to add wechat live room products
yami.live.room.wechat.not.exist = The room does not exist in the wechat live console
yami.live.prod.wechat.not.exist = The product does not exist on wechat live console
yami.category.one.check=The first level classification cannot be changed to the second level classification
yami.category.two.check=Secondary classification cannot be changed to primary classification
yami.category.superior.check=The superior of classification cannot be oneself
yami.category.name.exist=Category name already exists\uFF01
yami.category.status.check=Failed to modify. The superior classification does not exist or is not in normal status
yami.category.delete.check=There are goods under this category, please delete the goods under this category first
yami.category.delete.child=Please delete the subcategory and then delete the category
yami.score.select.num=Please select product
yami.score.select.num.shop=Please select the goods you need to purchase
yami.user.score.enough=Insufficient user points
yami.user.score.input.check=Please enter the correct number of points
yami.user.score.no.enough=Unable to submit order due to insufficient points
yami.user.score.prod=It's not a point product or an abnormal point price
yami.user.no.get.phone=Unable to get user's mobile phone number information
yami.user.account.error=Incorrect username or password
yami.user.account.exist=The user name already exists
yami.user.account.no.exist=user does not exist
yami.user.disabled = user is disabled, please contact customer service
yami.user.err.phone=Please enter a valid phone number
yami.user.account.lock=The account has been locked. Please contact the administrator
yami.user.account.lock.pre=The account has been locked due to:
yami.user.account.lock.after=, Please contact the administrator
yami.user.phone.exist=The mobile phone number has been registered, unable to re register
yami.user.name.check=The user name should consist of a 4-16 digit alphanumeric underline
yami.user.password.no.exist=New password cannot be empty
yami.user.password.check=The new password cannot be the same as the original password
yami.user.code.error=The verification code is wrong or expired
yami.user.code.empty=The verification code cannot be empty
yami.user.code.check.too.much=The verification code is checked too frequently. Please try again later
yami.verification.limit=The number of SMS verification codes sent today has reached the upper limit
yami.verification.time.check=The captcha can only be sent once a minute
yami.verification.expire=The verification code has expired. Please resend the verification code for verification
yami.sending.message.failed=Failed to send SMS. Please try again later
yami.user.login.error=Abnormal login information
yami.user.login.type=Unable to get login method
yami.user.unable.login.type=The login method is not implemented
yami.user.no.exist=Unable to get user information
yami.select.source=Please select material type
yami.user.level.no.exist=The membership level does not exist or the current level is not a paying member level
yami.user.pay.level.check=Users cannot purchase lower level members during the membership period
yami.user.growh.no.enough=Insufficient growth value of users, unable to purchase
yami.user.request.error=User related requests should start with / P!!!
yami.user.addr.update.error=Unable to modify user default address. Please try again later
yami.user.level.delete.error=This level cannot be deleted. At least one level must be kept
yami.shop.user.account.lock=Account has been locked, please contact the store administrator
yami.shop.sys.super.user.no.modify=Store Super Administrator, cannot be changed here
yami.shop.account.have.only.one=One store needs only one super administrator, please handle the store account data
yami.shop.data.is.removed=This data has been deleted
yami.shop.card.is.exist=This bank card number already exists
yami.distribution.close=Promotion plan closed
yami.distribution.set.exception=Distribution exception settings
yami.distribution.userWallet.banlance=You still have balance in your distribution account
yami.distribution.info.cardno=Application information is not complete, need ID card number
yami.distribution.info.pic=Application information is not complete, need ID card photo
yami.distribution.info.name=Application information is incomplete, real name is required
yami.distribution.submit.examine=You have submitted it for review. Please wait patiently
yami.distribution.ban.examine=The account has been permanently blocked
yami.distribution.clear.examine=It has been temporarily blocked and cannot be applied. Please contact the administrator
yami.distribution.success.examine=Your audit has passed, no need to review again
yami.distribution.get.examine=Unable to get the information of the invitee
yami.distribution.shop.error=The information of the inviting store is wrong
yami.distribution.user.error=You can't invite yourself
yami.distribution.user.Unqualified=If you do not meet the application conditions, please contact customer service to apply
yami.distribution.fee.error=The consumption amount does not meet the requirements
yami.distribution.fee.num=The number of consumption does not meet the requirements
yami.distribution.user.no.shop=You are not a distributor of the current store
yami.distribution.user.no.distributor=You are not a distributor yet
yami.distribution.user.no.distributor1=Your distribution identity is abnormal, please contact the administrator
yami.distribution.no.distributor=You are not a distributor yet. You cannot upgrade
yami.distribution.level.limit=The level limit has been reached
yami.distribution.level.condition=You are not eligible for upgrade
yami.distribution.cash.param1=The withdrawal amount cannot be empty
yami.distribution.cash.param2=The minimum withdrawal amount is $1
yami.distribution.cash.num=The number of withdrawals is
yami.distribution.cash.month=monthly
yami.distribution.set.error=The basic distribution setting information of the store was not found
yami.distribution.prod.exist.error=The distribution item information was not found
yami.distribution.prod.award=Fixed reward proportion cannot exceed 100%
yami.distribution.prod.level=The level reward proportion cannot exceed 100%
yami.distribution.prod.award.check=Fixed bonus settings cannot exceed the maximum price of an item
yami.distribution.prod.level.check=The level reward setting cannot exceed the maximum price of the product
yami.distribution.prod.parent.award=The fixed reward proportion of invitees cannot exceed 100%
yami.distribution.prod.parent.level=The level reward proportion of invitees cannot exceed 100%
yami.distribution.prod.parentAward.check=The invitee fixed reward cannot be greater than or equal to the highest price of the item
yami.distribution.prod.parentLevel.check=Inviter level reward cannot be greater than or equal to the highest price of the item
yami.distribution.prod.price.check=Reward setting cannot be greater than or equal to the highest price of the product or 100%
yami.distribution.prod.exist=Distribution item already exists
yami.distribution.exist.error=Distributor information not found
yami.distribution.enable.error=The merchant did not open the binding user mode
yami.distribution.extension.error=You have become the promoter of the shop, and cannot be promoted
yami.distribution.extension.time=You are still in the promotion period and cannot be promoted by new promoters
yami.distribution.user.protection.period=The user failed to bind during the protection period
yami.distribution.status.error=Promoter status abnormal
yami.distribution.get.fail=Failed to obtain promoter information
yami.distribution.batch.update.income=Failed to batch update distribution revenue status
yami.distribution.fee.than.error=The withdrawal amount is greater than the maximum withdrawal amount
yami.distribution.fee.less.error=The withdrawal amount is less than the minimum withdrawal amount
yami.distribution.balance.not.enough=Withdrawal failed, insufficient balance
yami.distribution.user.withdrawals=If you are not bound to WeChat, please log in with the WeChat Mini Program authorization before withdrawing cash
yami.sys.menu.exist=Menu URL cannot be empty
yami.sys.file.no.exist=The domain name of the file is not configured. The successful image cannot be uploaded
yami.sys.sms.no.exist=Unable to get SMS configuration, unable to send SMS
yami.sys.wxMa.no.exist=Please set the wechat applet information on the background page before operation
yami.sys.wxMp.no.exist=Please set up WeChat official account information on the background page before proceeding.
yami.sys.wxApp.no.exist=Please set the wechat application information on the background page before operation
yami.sys.wxPay.no.exist=Please set the wechat application information on the background page before operation
yami.sys.wxDomain.no.exist=Please set the callback domain name on the background page before operation
yami.sys.menu.child.delete=Please delete the submenu or button first
yami.sys.menu.delete.error=System menu, cannot be deleted
yami.sys.menu.user.error=You can't be your superior
yami.sys.menu.superior.list=The superior menu can only be directory type
yami.sys.menu.superior.menu=The superior menu can only be a menu type
yami.sys.role.identical.name=The same role name already exists in the system
yami.document.no.content=The document has no content
yami.file.error=File format error
yami.modified.settlement.information=Settlement information changed
yami.platform.num.check=Platform today
yami.num.limit=The number of times available has reached the maximum!
yami.sys.delete.error=Current user cannot delete
yami.sys.admin.error=System administrator cannot delete
yami.sys.select.user=Please select the user to be deleted
yami.sys.user.already=The user already exists
yami.sys.sms.package=The purchased SMS package does not exist. Please refresh and try again
yami.sys.sms.package.limit=The number of packages has reached the upper limit of 10, please delete and add again!
yami.sys.illegalArgument=Illegal request parameter, please check!
yami.cannot.get.app.info=Unable to get app information
yami.same.key=A key with the same configuration already exists in the system
yami.sys.paypal.no.exist=Please set up paypal related information in the backend page before proceeding
yami.address.deleted=Order item does not exist
yami.item.has.commented=Changed order item has been commented, please do not repeat common
yami.item.com.repeated=Order comment has been submitted
yami.confirm.receipt=Please confirm receipt before common
yami.comment.is.delete=Evaluation does not exist or has been deleted, please return and refresh to try again
yami.cannot.reapply=You have applied to open the store. You cannot apply again
yami.shop.num.check=Shop today
yami.store.name.exist=Shop name already exists
yami.store.not.exist=Store information not found
yami.shop.not.category=The current store does not have a signed platform classification, please sign the classification first
yami.station.account.exist=This account already exists. Please enter a new account
yami.store.account.exist=The account already exists, please re-enter
yami.store.apply.no.exist=Application information not found
yami.store.offline.check=The store is not open or closed, and cannot be offline
yami.shop.company.repeat.application=You cannot submit multiple change applications at the same time,please revoke the application submitted last time and apply again
yami.cannot.update.wallet=Failed to update store wallet information
yami.cannot.distribution.update.wallet=Failed to update promoter wallet information
yami.store.brand.name.error=The brand name already exists
yami.my.store.no.cash=Self operated stores cannot withdraw cash
yami.shop.cash.too.less=The amount of withdrawal shall not be less than 1.00 RMB
yami.shop.cannot.delete.card=Default card cannot be deleted
yami.shop.max.card.num=The maximum number of bank cards has been reached and cannot be added
yami.shop.least.one.card=Keep at least one bank card
yami.shop.cannot.delete.check=The bank card used to apply for withdrawal cannot be deleted
yami.shop.station.close=The pickup point has been closed. Please contact the administrator
yami.shop.station.not.open=The pick-up point is not in operation
yami.shop.phone.no.exist=Mobile phone number cannot be empty
yami.shop.update.balance=Failed to update balance record. Please try again later
yami.shop.cash.no.enough=Insufficient withdrawal amount
yami.shop.cash.grant=Cash withdrawal and distribution
yami.shop.company.credit.code.repeat=Duplicate unified credit code
yami.shop.business.date.error=The business start date cannot be greater than or equal to the business end time
yami.shop.company.date.not.empty=Business date cannot be empty
yami.shop.bank.card.not.empty=At least one bank card must be added
yami.shop.bank.card.no.repeat=Duplicate account
yami.shop.bank.card.max.limit=The number of bank cards cannot exceed
yami.cash.grant=Cash withdrawal
yami.open.store=Please apply for shop opening first
yami.password.error=The original password is incorrect
yami.stop.cannot.modified=Store account has been set and cannot be modified
yami.stop.examine.success=The business has been approved successfully, no need to audit again
yami.stop.cannot.open=The account has been opened and cannot be opened again
yami.sign.check=Signature verification failed
yami.bar.code.exist=Single item barcode already exists
yami.select.only.shop.type=Please select a store type
yami.select.a.shop=Please select a store
yami.transaction.not.exists=Transaction number does not exist
yami.query.error=Query error
yami.order.no.exist=Order does not exist
yami.order.is.delivery=The order has already been partially shipped and cannot be shipped in bulk
yami.order.amount.error=The order amount is wrong and cannot be paid
yami.order.amount.too.large.error=The order amount is too large and cannot be paid
yami.order.code.no.exist=The checkout code, there is no corresponding order
yami.order.code.no.error=Checkout code error
yami.h5.index.ad.images.limit=Rotation ads limit 10
yami.order.payed=Order has been paid and cannot be cancelled
yami.order.not.paid=The current order has not been paid, unable to apply
yami.order.has.failed=The current order has failed. No refund is allowed
yami.order.receipt.no.delivery=Order not shipped, cannot confirm receipt
yami.order.pay.user.disable=You have been disabled and cannot purchase. Please contact the customer service of the platform
yami.order.status.no.right=The order is not in the status to be put into storage, so it cannot be put into storage
yami.order.delivery.no.right=The order is not in the status of waiting for shipment and cannot be delivered
yami.order.pay.fail=Payment failed. The order is not in unpaid status
yami.order.no.delivery=The order is not in the waiting state and cannot be confirmed
yami.order.delivery.refund.error=The order has refund information in process, please process it before shipment!
yami.order.receipt.refund=Order refund, cannot confirm receipt
yami.order.no.success=In order refund, the order is not completed or closed, so the order cannot be deleted
yami.order.no.dvyName=The name of the courier company can not be empty
yami.order.delivery.number=Wrong format of courier bill number
yami.order.delivery.error=When multiple stores submit orders, the delivery method can only be express delivery
yami.order.same.city.error=The current shop does not open the same city distribution!
yami.order.same.city.error2=The delivery distance is exceeded or the starting fee is not enough!
yami.order.same.city.error3=Current orders do not support same-city delivery!!
yami.order.same.city.error4=Exceeds the currently set delivery distance!
yami.order.unrecognized.prod=The order status is abnormal, the order address cannot be changed
yami.order.unrecognized.update=Order status is abnormal, order amount cannot be changed
yami.order.amount.check=The order amount must be greater than 0, or the data has changed (please refresh and try again)
yami.order.status.error=The order contains unrecognized items
yami.order.status.change=Order status has changed, please do not repeat operation
yami.order.status.check.change=The order status has changed, please place the order again
yami.order.submit.change=Please do not submit orders repeatedly
yami.order.refund.status.exist=Return status cannot be empty
yami.order.refund.exist=Refund note does not exist
yami.order.refund.define=Please confirm the refund before starting the refund operation
yami.order.refund.success=The refund has been successful. You cannot apply for refund again
yami.order.refund.cancel=The buyer has cancelled the application
yami.set.refund.information=Please select return address
yami.order.refund.day.check=The current order has received more than
yami.order.refund.day.check2=Days, no refund
yami.no.found.order=The order information was not found
yami.order.refund.score=Credit products, no refund
yami.availabl.cash.refund=Your cash withdrawal amount is insufficient and cannot be refunded
yami.not.sufficient.refund=Your amount to be settled is insufficient and cannot be refunded
yami.refund.processed=The refund has been processed and no repeat processing is required
yami.order.all.refund.go.on=The order already has goods in the process of refund, so the whole order cannot be refunded
yami.order.all.refund.check=The whole order is being refunded. No new refund operation can be performed
yami.order.need.station=Please select at least one order to be picked up by yourself
yami.order.refund.go.on=This product is in the process of being refunded. New refund operation cannot be performed
yami.refund.exceeded.amount=The refund amount has exceeded the order amount, unable to apply
yami.not.refunds.requested=No payment record found, unable to apply for refund
yami.refund.progress=The order is in the process of refund settlement, please do not repeat the operation
yami.unable.refund.information=Unable to get refund order information
yami.refund.amount.check=The payment amount and points of some order items of this order are 0, partial refund cannot be used!
yami.refund.platform.amount.check=There is a refund for this order. You can't use this platform!
yami.refund.num.check=The quantity of refund items has exceeded the quantity in the order. Application is not allowed
yami.order.processed=Refund order item has been processed, please do not apply again
yami.order.unfinished.cannot.destroy.account=you still have unfinished orders. Please wait until all orders have been finish
yami.cannot.find=No found refund information
yami.not.permission=Application failed. You do not have the permission
yami.not.submission=The current application type is not allowed to submit logistics information
yami.not.submission.delivery=Current status does not allow to submit logistics information operation
yami.not.update.delivery=Update of logistics information is not allowed in current status
yami.revocation.failed=Cancellation failed. The refund order does not exist
yami.shop.processing.check=The seller is processing a refund and cannot cancel the refund request
yami.user.delivery.check=The buyer has delivered the goods and cannot cancel the refund application
yami.user.receipt.check=The seller has received the goods and cannot cancel the refund application
yami.refund.success.check=Refund successful. Refund application cannot be cancelled
yami.refund.finish.check=All items in the order are refunded and cannot be cancelled
yami.refund.status.check=Undo failed. This operation is not allowed in the current state
yami.failed.not.exist=Failed to view. The refund order does not exist
yami.failed.not.permiso=Failed to view. You do not have this permission
yami.item.not.exist=The item does not exist in the order
yami.shopCart.take.off=Off the shelf
yami.contains.unrecognized.items=The shopping cart contains unrecognized items
yami.no.auth.update.form=You do not have permission to change the data of this report
yami.auth.fail=Authorization failed. Please re authorize
yami.img.name.exist=Picture name cannot be empty
yami.area.delete=Please delete sub region first
yami.delivery.using=In use, cannot delete
yami.selCity=Please select the designated city for package delivery
yami.model=Template
yami.img.lose=The picture is missing. Please upload the picture again
yami.unable.get.classification=Unable to get classification information
yami.select.notify.check=Please select at least one notification method
yami.select.notify.type.check=Other configuration of the current message type already exists. Please go to modify it.
yami.flush.category.tips=Please go to [member management] > [point growth value configuration] - > [point acquisition configuration] to configure and save
yami.form.time.check=Please select the start and end time
yami.form.data.error=The report data is incorrect, please refresh and re-enter
yami.coupon.no.auth=You have no permission to modify the coupon information
yami.coupon.receive.finish=The voucher cannot be collected or the voucher is finished!
yami.coupon.stock.enough=Insufficient coupon stock
yami.coupon.user.limit=The coupon has reached the upper limit of individual claim and cannot continue to receive it\uFF01
yami.coupon.limit.check=The limited quantity of coupons should be greater than 0
yami.coupon.time.check=Start time should be greater than end time
yami.coupon.launch.time.check = Coupon placement time cannot be empty
yami.coupon.launch.time.check1 = The casting time needs to be greater than the current time
yami.coupon.launch.time.lt.endtime = The Lanuch time needs to be less than the end time
yami.coupon.no.exist=Coupon does not exist
yami.coupon.delete.check1=The coupon has been claimed. Deletion failed
yami.coupon.delete.check2=The coupon has been put in, failed to delete
yami.coupon.receive.success=Coupon received successfully
yami.live.time.check=The start time cannot be greater than the end time
yami.live.time.one.check=The start time should be 10 minutes after the current time, and not after 6 months!
yami.live.time.two.check=The interval between the start time and the end time should not be less than 30 minutes or more than 24 hours!
yami.live.name.check=Name length does not conform to the rule!
yami.live.user.name.check=The host micro signal does not have real name authentication by \u3010\u5C0F\u7A0B\u5E8F\u76F4\u64AD\u3011\uFF01
yami.live.room.check1=not configured in the applet management background customer service
yami.live.config.check=Failed to create. Please check the configuration of the live room carefully\uFF01
yami.live.platform.numLimit=The number of times that the platform can get the live broadcast room information today has reached the limit\uFF01
yami.live.prod.name.check=Illegal name length, at least 3 Chinese characters or 6 characters, maximum 14 Chinese characters!
yami.live.room.name.check=The length of the name of the studio is illegal, the shortest is 3 Chinese characters, and the longest is 17 Chinese characters!
yami.live.room.name.check2=The length of the host's nickname is illegal, the shortest is 2 Chinese characters, and the longest is 15 Chinese characters
yami.live.room.top.check=The ceiling has reached the upper limit of 10, which cannot be set. Please cancel the topping of other live broadcasting rooms first
yami.live.prod.delete.fail=Failed to delete live product
yami.live.room.delete.fail = Failed to delete live room
yami.live.prod.update.fail=Failed to update live product library
yami.live.prod.not.exist=The product associated with the current live broadcast product does not exist or has been deleted
yami.live.prod.examine=The product is under review and cannot be modified
yami.live.img.isWebp=Pictures cannot use webp format, jpg or png is recommended
yami.prod.pre.sell=Pre sale items cannot be added to the shopping cart!
yami.order=order
yami.order.station.check=Refund, unable to collect
yami.order.station.finish=Picked up
yami.prod.no.join.activity=The current product did not participate in the activity
yami.activity.no.start=At present, the activity of group organization has not started
yami.activity.already.end=The current group activity has ended
yami.activity.already.invalid=The current group activity is invalid
yami.job.get.error=Exception in getting crontrigger for timed task
yami.prod.category.error=Please select the three-level classification of the platform
yami.notify.tag.msg=Please select at least one label!
yami.user.payType.error=Please use WeChat or Alipay for payment.
yami.information.is.wrong=Your information is wrong, please try to refresh before operation
yami.balance.is.insufficient=Your balance is insufficient, please recharge the balance first
yami.id.number.already.exists=The ID number already exists.
yami.phone.number.already.exists=The phone number already exists in the system.
yami.phone.number.not.exists=The account does not exist
yami.get.user.cash.info=Unable to obtain withdrawal information
yami.get.user.withdraw.info=Unable to get user wallet information
yami.withdrawCash.update.no.auth=No permission to modify withdrawal information
yami.user.tag.not.exists=User tag does not exist
yami.user.tag.type.not.right=User tag type not right
yami.user.tag.refresh.limit=The refresh interval cannot be less than one minute
yami.user.tag.time=The start time cannot be later than the end time
yami.user.tag.number=The minimum number cannot be greater than the maximum number
yami.user.tag.amount=The minimum amount cannot be greater than the maximum amount
yami.finance.transactionTime=Transaction Time
yami.finance.orderNumber=Order Number
yami.finance.incOrPay=Pay Or Income
yami.finance.payType=Payment Method
yami.finance.transactionAmount=Transaction Amount
yami.finance.reportTitle=Financial Statement
yami.finance.income=Income
yami.finance.pay=Pay
yami.payType.pay0=Point Payment
yami.payType.pay1=WeChat Payment
yami.payType.pay2=Alipay Payment
yami.payType.pay3=WeChat Scan Code Payment
yami.payType.pay4=WeChat H5 Payment
yami.payType.pay5=WeChat Official Account Payment
yami.payType.pay6=Alipay H5 Payment
yami.payType.pay7=Alipay APP Payment
yami.payType.pay8=WeChat APP Payment
yami.payType.pay9=User balance Payment
yami.store.name.no.exist=Store name cannot be empty
yami.store.name.check1=Product name length should be less than {max}
yami.tag.num.check=The number of condition tags exceeds the upper limit
yami.tag.shop.check=You are not authorized to operate this product label
yami.tag.prod.check=Please select the products to be grouped
yami.tag.prod.delete.check=Please select the product in the group to be deleted
yami.tag.prod.update.check=Please select the goods in the group to be modified
yami.live.user.check=Wechat account non compliance
yami.live.user.check1=Wechat account signal needs real name authentication, which may appear only when the host role is set
yami.live.user.check2=Add role repeatedly
yami.live.user.check3=Added role reaches the upper limit
yami.live.user.check4=Failed to delete the anchor role. There is a live room that has not been started
yami.live.user.super.admin=Super administrator\uFF0C
yami.live.user.admin=administrators\uFF0C
yami.live.user.anchor=anchor\uFF0C
yami.live.user.operators=Operators\uFF0C
yami.live.user.check5=The user already has a manager role
yami.live.user.check6=Host role deletion failed, the host does not exist or there is a live room that is not open
yami.tag.name.exist=Label name already exists
yami.customer.no.online=The customer service or user selected to forward is no longer online and cannot be forwarded!
yami.user.balance.check=The current balance of the user is insufficient and cannot be reduced
yami.excel.user.info=User Information Form
yami.excel.user.number=Serial number
yami.excel.user.userNickname=User nickname
yami.excel.user.userName=User Name
yami.excel.user.contactNumber=Contact number
yami.excel.user.memberLevel=Membership Level
yami.excel.user.memberType=Membership Type
yami.excel.user.accScore=User score
yami.excel.user.status=Status
yami.excel.user.amountConsum=Spending amount
yami.excel.user.amountActPaid=Actual amount paid
yami.excel.user.numberConsum=Number of consumption
yami.excel.user.aveDiscount=Average Discount
yami.excel.user.rechargeAmount=Recharge amount
yami.excel.user.topUpTimes=Recharge times
yami.excel.user.refundAmount=Refund amount
yami.excel.user.numberOfRefund=Number of refunds
yami.excel.user.accPoints=Accumulated score
yami.excel.user.currBalance=Current Balance
yami.excel.user.accBalance=Accumulated Balance
yami.excel.user.regTime=Registration Time
yami.excel.user.receConsumDate=Latest consumption time
yami.web.config.check=Please turn on at least one configuration and then turn off the current configuration
yami.average.retention.rate=Average retention rate
yami.prod.set.top.check=You can only top items that are already on the shelves
yami.login.password.check=The login has been restricted for 30 minutes after entering the password incorrectly ten times within half an hour.
yami.product.sku.invalid=Stock is invalid
yami.group.name.duplicate=Group name already exists
yami.invoice.shopId.notNull=Shop id cannot be empty
yami.invoice.invoiceId.duplicate=This order has already requested an invoice, please do not repeat it!
yami.invoice.not.user=Unable to view invoice information for non-current users
yami.file.isNot.exist=Please upload the file
yami.file.isNot.shop=Unable to view files that are not in our store
yami.prod.common.invalid=Data has expired, please refresh the page
yami.station.no.exist=Pickup point information does not exist, please select a new pickup point
yami.prod.name.not.blank=Product Chinese name cannot be empty
yami.prod.name.en.not.blank=Product English name cannot be empty
yami.prod.brief.not.blank=Product Chinese brief cannot be empty
yami.prod.category.not.blank=Product category cannot be empty
yami.platform.category.not.blank=Platform category cannot be empty
yami.prod.shop.type.not.blank=Product type cannot be empty
yami.prod.shop.category.not.blank=Product shop category cannot be empty
yami.prod.dvy.type.not.blank=Product delivery method cannot be empty
yami.prod.transport.not.exist=Product shipping templates do not exist
yami.prod.pic.limit = The number of uploaded pictures exceeds the limit
yami.prod.pic.format.error = Uploaded picture format error
yami.prod.video.format.error = Upload video format error
yami.prod.video.too.large.error = Uploaded video is too large
yami.product.not.shelf=This product is not on the shelf, please select another product
yami.supplier.name.not.blank=Supplier name cannot be empty
yami.supplier.not.null=Supplier cannot be empty
yami.supplier.supplierName.exist=Supplier name already exists
yami.supplier.supplierName.than=The number of words in the name of the supplier cannot exceed 50
yami.supplier.contactName.than=Contact name cannot exceed 50
yami.supplier.tel.error=Wrong format of unit phone number
yami.supplier.contactTel.error=Wrong format of contact number
yami.supplier.mail.error=Mailbox format error
yami.supplier.qqNumber.error=The qq number is malformed
yami.supplier.wxNumber.error=WeChat format error
yami.supplier.prod.not.shop=Cannot view items that are not in our shop
yami.sku.party.code.exist=Product code already exists
yami.sku.party.code.not.exist=The product code does not exist or the product has been deleted
yami.sku.party.code.is.repeated=There are multiple product specifications under this product code, please update the corresponding product specification code and re-import it.
yami.supplier.category.not.exit=Supplier classification does not exist or has been disabled
yami.supplier.category.already.exit=Supplier categories already exist
yami.order.not.null=The required fields for the order cannot be empty\uFF01
yami.order.coupon.not.start=Card vouchers are not up for use or have expired
yami.order.coupon.expired=Card voucher has expired
yami.order.coupon.exist=Card vouchers do not exist or have been cancelled!
yami.order.virtual.check=Refund in progress, can't write off!
yami.order.virtual.check2=Current virtual goods orders do not require write-off
yami.virtual.prod.check=Virtual products cannot be added to the shopping cart
yami.order.virtual.refund.check1=Current order can not be refunded, please contact customer service
yami.order.virtual.refund.check2=virtual goods orders cannot be returned for refund
yami.order.virtual.refund.check3=The current order has expired and cannot be refunded, please contact customer service
yami.order.virtual.refund.check4=The current order has been fully checked out and cannot be refunded, please contact customer service
yami.order.virtual.refund.check5=The number of refunds available for the current order is exceeded
yami.order.prod.type.check=Product type cannot be modified after product creation
yami.prod.type.check=Product type changed, please refresh the page and try again
yami.take.stock.time.not.null=Inventory start time cannot be empty
yami.take.stock.prod.null=Inventory items cannot be empty
yami.take.stock.id.not.null=Inventory Id cannot be empty
yami.take.stock.message.error=Current inventory information does not belong to your store
yami.take.stock.status.error=The current inventory task has been completed or invalidated, please return to the list page and refresh
yami.take.stock.import.error=The inventory list already has products imported, so you cannot use the bulk import function.
yami.take.stock.count.not.null=Inventory quantity cannot be empty
yami.shop.sku.is.null=Product specifications do not exist
yami.shop.stock.update.error=Inventory update failure
yami.shop.total.stock.not.null=The actual inventory of the product cannot be empty
yami.purchases.order.voided=This order has been voided
yami.purchases.order.complete=This order has been complete
yami.purchases.order.party.code=Product code cannot be empty
yami.purchases.order.stock.num=Purchase number cannot be empty
yami.purchases.order.error.code=Wrong product code
yami.supplier.status.error=This provider is disabled, please enable it before operation
yami.sku.party.code=Product Code
yami.sku.stockWarning.limit = StockWarning is greater than maxvalue
yami.is.exist=Already exists
yami.properties=Sales Property Combination String
yami.properties.error=Format error
yami.sku.name=Specification name
yami.is.duplicate=is repeat
yami.supplier.not.exist.or.disabled=Supplier does not exist or is disabled
yami.purchased.order.not.exist=Purchased order do not exist, please refresh and try again!
yami.purchased.prod.not.exist.or.disabled=Purchased items do not exist or have been deleted, please refresh and try again!
yami.data.deleted.or.not.exist=Data has been deleted or does not exist
yami.platform.prod.offline.check=The current product/activity has been removed from the shelves or is under review, and cannot be removed from the shelves
yami.order.coupon.expire.check=The currently selected coupon has expired, please return to resubmit the order
yami.order.discount.expire.check=The currently selected full discount activity has expired, please return to resubmit the order
yami.order.combo.expire.check=The currently selected package activity has expired, please return to resubmit your order
yami.order.giveaway.expire.check=The currently selected giveaway event has expired, please return to resubmit your order
yami.order.pay.type.check=The platform does not support the current payment method, please refresh and select after
yami.platform.delivery.name.repeat=Logistics name cannot be repeated
yami.prod.parameter.format.error=Wrong format of product parameters
yami.balance.than.max.balance=Your balance plus recharge balance will be greater than the maximum balance. Recharge operation is not allowed
yami.user.blance.not.exist = The current recharge option no longer exists, please refresh and try again
yami.prod.status.change=Product status has changed, please refresh the page
yami.refund.amount.change.check=Current refund order status cannot change refund amount, please try again later
yami.refund.amount.change.check2=Refunds for whole orders do not support changing the refund amount at this time
yami.refund.amount.change.check3=The refund amount cannot be modified for orders using the platform offer
yami.order.delivery.num.check=Insufficient number of orders shipped, please refresh and try again
yami.active.is.delete=The activity has been deleted, please refresh the page and try again
yami.station.no.exists=Current store does not exist or is not in business status, please try again
yami.exprot.prod.sku.error=If there are products with more than 100 groups of specifications detected, please modify them and re-import them.
yami.combo.end.time.error=Event end time cannot be less than current time
yami.combo.main.prod.not.empty=Package main product cannot be empty
yami.combo.matching.prod.count.error=Wrong number of matching products
yami.combo.prod.delete.after.tips=Has been deleted, please select again
yami.combo.prod.matching.price.after.tips=The matching price cannot exceed the original price of the product
yami.combo.not.shop=The current package does not belong to your shop
yami.combo.already.delete=The current package has been deleted
yami.combo.update.fail=Package information update failed, please refresh and try again
yami.combo.matching.required.not.empty=Please set at least one required matching product
yami.combo.open.error.tips=The end time of the current package is less than the current time, the opening fails, please set the activity time of the package first
yami.combo.least.num.not.empty=The starting quantity cannot be empty
yami.combo.not.find.prod=Can't find product information
yami.combo.info.error=info error
yami.combo.already.invalid=The current package activity has expired
yami.combo.product.already.delete.rear.tips=Has been deleted, please select again
yami.combo.product.already.disable.rear.tips=Has been disabled, please select again
yami.combo.spec.already=specifications
yami.combo.delete.fail=Delete failed, please refresh and try again
yami.giveaway.not.on.shop=The gift information does not belong to your shop
yami.giveaway.prod.error=There are wrong products, please refresh and select again
yami.giveaway.virtual.prod.error=It is a virtual product and cannot be set as a gift product
yami.giveaway.activity.time.error.tips1=Activity time and gifts\u3010
yami.giveaway.activity.time.error.tips2=\u3011The time conflicts, one main product cannot set up multiple gift activities at the same time,\u3010
yami.giveaway.activity.time.error.tips3=\u3011Activity time for
yami.giveaway.activity.time.error.tips4=The end time of the current gift is less than the current time, the opening fails, please set the event time of the gift first
yami.giveaway.activity.time.error.tips5=No multiple giveaways can be set up for one main product
yami.giveaway.time.to=to
yami.giveaway.already.invalid=The current gift event has expired
yami.giveaway.already.delete=The current giveaway has been deleted
yami.giveaway.update.fail=Failed to update gift information, please refresh and try again
yami.giveaway.refund.price.error=The total return price of the gift cannot exceed the price of the main product
yami.prod.combo.expired=Product combo does not exist, or has expired
yami.main.prod.wrong=The main product information is wrong, please refresh and try again
yami.select.matching.prod=Please select matching products
yami.select.required.matching.items=Please select the required matching items
yami.prod.package.cannot.empty=Product package with product list cannot be empty
yami.active.prod.cannot.add.cart=Active items cannot be added to the shopping cart
yami.active.prod.cannot.add.collection=Active items cannot be added to collection
yami.active.prod.cannot.buy=Active items cannot be purchased separately
yami.combo.prod.already.exists=There is already a package of this size in your shopping cart, please do not add to it.
yami.specification.already.exists.shopping.cart=The specification already exists in the shopping cart
yami.cn.reason.duplicate=Chinese reason is repeated, please re-enter
yami.en.reason.duplicate=English reason is repeated, please re-enter
yami.system.reason.not.delete=System built-in in/out reasons cannot be deleted
yami.sku.price.not.change=participated in the package or giveaway activities, can not change the price, please refresh the page and try again
yami.combo.prod.not.delete=Products participating in the following activities cannot be removed: Discount packages
yami.giveaway.prod.not.delete=Items participating in the following events cannot be removed: Giveaways
yami.sys.web.config.delete=Active configuration cannot be deleted
yami.imgs.length.then.max=IMGs data error: length greater than 255
yami.seckill.invalid=The second kill activity has expired
yami.not.ordinary.prod= is not an ordinary Product
yami.lack.permission.pre=You lack the permission of
yami.lack.permission.suf= module
yami.refund.amount.check1=Refund amount is wrong, please re-enter
yami.role.use.cannot.deleted=Role in use cannot be deleted
yami.prod.platform.category.deleted=This platform category has been deleted, please select a new category
yami.index.img.reached.limit=The maximum number of rotation pictures on this client has been reached, so you can't add any more
yami.shopCart.prod.error=Pre-sale, virtual, and event items cannot be added to the cart!
yami.sku.cannot.empty=SKU list cannot be empty
yami.signingAuditing.auditInformation.notfound=Could not find this audit information, please refresh the page
yami.Auditing.applicationInfo.notFound=Application information could not be found, please refresh the page
yami.signingAuditing.categorySigningInformation.notFound=The category signing information does not exist or is incorrect. Please refresh the page
yami.invoice.categoryId.notNull=The category ID cannot be empty
yami.invoice.brandId.notNull=The brand ID cannot be empty
yami.not.permission.modify.administrator.info=You do not have permission to modify administrator information
yami.order.devType.notMatch=The imported shipping method is inconsistent with the shipping method for the order
yami.out.orderNumber=external order number
yami.pay.status=payment status
yami.pay.score=payment points
yami.pay.amount=payment amount
yami.pay.time=payment time
yami.order.pay=payed
yami.order.no.paid=not paid
yami.pay.info.reportTitle=revenue reconciliation detail report
yami.refund.info.reportTitle=Refund Reconciliation Detail Report
yami.account.info.reportTitle=Reconciliation Detail Report
yami.pay.no=payment number
yami.refund.no=Refund order number
yami.refund.status=Refund status
yami.refund.time=Refund time
yami.refund.finish=Refunded
yami.message.leng.exceed.limit=Message content length exceeds limit
yami.order.is.closed=Orders are closed
yami.deliverySum.exceed.stocks=Outgoing quantity exceeds stock quantity
yami.shop.pay.info.update.error=Payment information update failed
yami.prod.import.virtualRemark.notValid=The message format for virtual goods is incorrect
yami.sensitive.words.reenter=There are sensitive words, please re-enter
yami.prod.status.error.Please.exit.and.try.again=The status of the product is incorrect Please exit and try again
yami.finance.form.excel=Please select the transaction time for exporting reports
yami.shop.wallet.log.excel=Store billing schedule
yami.Shipping.amount.error=Shipping amount cannot be less than 0
yami.balance.out.error=balance must not exceed 9999999999.99
yami.score.out.error=score must not exceed 100000000
yami.trans.amount.not.null=The shipping cost cannot be empty when the flat rate is applied
yami.delivery.name.is.same=Duplicate with the system built-in template name, please re-enter
yami.delivery.error=Please select a shipping region
yami.delivery.over=Shipping is not supported in the current region
yami.cannot.used.score.payment=Orders with payment amount greater than 0 cannot be paid with points
yami.combo.price.excessive=The total amount of the combo is too large, please set it properly
yami.order.prod.count.limit=The number of products ordered cannot be less than 1
yami.product.has.created.seckill=This product has created a seckill activity, please do not submit again
yami.pcdn.error=The system is busy, please try again later
yami.pcdn.assets.freeze=The frozen quantity must be between 100 and 9999
yami.user.assets.lucky.coin.balance=Insufficient balance of lucky coins
yami.user.assets.lucky.coin.freeze=Freeze coin is  null as param
yami.user.device.not.exist=The user device does not exist
yami.pcdn.device.bound=The device has been bound
yami.pcdn.device.delete=The device has been deleted
yami.pcdn.device.token=Please set the configuration file for obtaining tokens
yami.pcdn.device.id.null=The device id is empty
yami.pcdn.device.userId.null=The user id is empty
yami.pcdn.device.binding.error=The device is already bound to your account
yami-shop-common/src/main/resources/i18n/messages_zh.properties
New file
@@ -0,0 +1,734 @@
yami.activity.cannot.delete=\u8BE5\u6D3B\u52A8\u72B6\u6001\u4E0B\u4E0D\u80FD\u8FDB\u884C\u5220\u9664
yami.activity.prod.cannot.delete=\u6D3B\u52A8\u8FDB\u884C\u4E2D\uFF0C\u4E0D\u80FD\u5220\u9664\u6D3B\u52A8\u5546\u54C1\uFF0C\u60A8\u53EF\u4EE5\u7B49\u5F85\u6D3B\u52A8\u7ED3\u675F\u540E\u6216\u5931\u6548\u8BE5\u62FC\u56E2\u6D3B\u52A8\u540E\u8FDB\u884C\u64CD\u4F5C
yami.activity.cannot.find=\u672A\u627E\u5230\u6B64\u6D3B\u52A8\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5
yami.activity.cannot.find.check=\u8BE5\u6D3B\u52A8\u4E0D\u5B58\u5728\u3001\u672A\u5F00\u59CB\u6216\u8005\u5DF2\u7ED3\u675F
yami.activity.prod.no.exist=\u6D3B\u52A8\u5546\u54C1\u4E0D\u5B58\u5728\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5
yami.activity.prod.status=\u6D3B\u52A8\u4E2D\u5305\u542B\u5DF2\u4E0B\u7EBF\u5546\u54C1
yami.activity.prod.update.error=\u66F4\u65B0\u6D3B\u52A8\u5546\u54C1\u5931\u8D25
yami.activity.prod.no.auth=\u60A8\u65E0\u6743\u5BF9\u6B64\u6D3B\u52A8\u5546\u54C1\u8FDB\u884C\u64CD\u4F5C
yami.activity.no.auth=\u60A8\u65E0\u6743\u64CD\u4F5C\u6B64\u6D3B\u52A8
yami.activity.add.prod.empty=\u6DFB\u52A0\u62FC\u56E2\u5546\u54C1\u4E0D\u80FD\u4E3A\u7A7A
yami.activity.enable.prod.empty=\u542F\u7528\u5931\u8D25\uFF0C\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u4E2A\u6D3B\u52A8\u5546\u54C1
yami.activity.disable=\u5931\u6548\u5931\u8D25\uFF0C\u6D3B\u52A8\u4E0D\u5728\u8FDB\u884C\u4E2D\u6216\u9884\u70ED\u72B6\u6001\u65E0\u6CD5\u8FDB\u884C\u5931\u6548\u64CD\u4F5C
yami.activity.info.check=\u8BF7\u586B\u5199\u5B8C\u6574\u6EE1\u51CF\u4FE1\u606F
yami.activity.item.check=\u6D3B\u52A8\u9879\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u6700\u5C11\u8981\u6709\u4E00\u4E2A\u6D3B\u52A8\u9879
yami.activity.status.check=\u8BE5\u6D3B\u52A8\u5DF2\u88AB\u5E73\u53F0\u4E0B\u7EBF\uFF0C\u4E0D\u80FD\u518D\u66F4\u6539\u72B6\u6001
yami.activity.now.over.end.time=\u5F53\u524D\u65F6\u95F4\u5DF2\u8D85\u8FC7\u6D3B\u52A8\u7ED3\u675F\u65F6\u95F4\uFF0C\u4E0D\u80FD\u542F\u7528\u6D3B\u52A8
yami.activity.add.success=\u6DFB\u52A0\u6210\u529F
yami.activity.update.success=\u4FEE\u6539\u6210\u529F
yami.submitted.successfully=\u63D0\u4EA4\u6210\u529F
yami.submitted.examine=\u5DF2\u63D0\u4EA4\u5BA1\u6838
yami.no.auth=\u6CA1\u6709\u6743\u9650\u8FDB\u884C\u64CD\u4F5C
yami.delete.successfully=\u5220\u9664\u6210\u529F
yami.undo.successfully=\u64A4\u9500\u6210\u529F
yami.address.added.successfully=\u6DFB\u52A0\u5730\u5740\u6210\u529F
yami.address.modified.successfully=\u4FEE\u6539\u5730\u5740\u6210\u529F
yami.deleted.address.successfully=\u5220\u9664\u5730\u5740\u6210\u529F
yami.address.exists=\u8BE5\u5730\u5740\u5DF2\u5B58\u5728
yami.address.add.limit=\u6536\u8D27\u5730\u5740\u5DF2\u8FBE\u5230\u4E0A\u9650\uFF0C\u65E0\u6CD5\u518D\u65B0\u589E\u5730\u5740
yami.address.cannot.delete=\u9ED8\u8BA4\u5730\u5740\u65E0\u6CD5\u5220\u9664
yami.user.address.delete=\u8BE5\u5730\u5740\u5DF2\u88AB\u5220\u9664
yami.user.receive.score=\u9886\u53D6\u79EF\u5206\u6210\u529F
yami.user.receive.score.check=\u4ECA\u5929\u5DF2\u7ECF\u7B7E\u5230\u8FC7\u4E86\uFF0C\u8BF7\u660E\u5929\u518D\u8BD5\uFF01
yami.shopCart.enter.num=\u8F93\u5165\u66F4\u6539\u6570\u91CF
yami.constant.code.expire=\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F
yami.network.exception=\u7F51\u7EDC\u5F02\u5E38
yami.network.busy=\u670D\u52A1\u5668\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5
yami.examine.fail=\u63D0\u4EA4\u5BA1\u6838\u5931\u8D25
yami.examine.already=\u8BE5\u7533\u8BF7\u5DF2\u88AB\u5BA1\u6838
yami.examine.status.error=\u5BA1\u6838\u72B6\u6001\u6709\u8BEF
yami.get.goods=\u83B7\u53D6\u5546\u54C1\u5217\u8868\u5931\u8D25
yami.request.error=\u7B2C\u4E09\u65B9\u8BF7\u6C42\u5931\u8D25\uFF1A
yami.request.data.too.long=\u8BF7\u6C42\u6570\u636E\u8FC7\u957F
yami.address.receiver.length.limit=\u6536\u8D27\u4EBA\u540D\u79F0\u592A\u957F\u4E86
yami.group.team.no.exist=\u672A\u627E\u5230\u62FC\u56E2\u56E2\u961F\u4FE1\u606F
yami.group.order.update.fail=\u66F4\u65B0\u62FC\u56E2\u8BA2\u5355\u4E3A\u5F85\u53D1\u8D27\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5
yami.group.team.no.join=\u62FC\u56E2\u56E2\u961F\u4E0D\u5728\u62FC\u56E2\u4E2D\uFF0C\u4E0D\u80FD\u53C2\u4E0E\u62FC\u56E2
yami.group.no.progress=\u62FC\u56E2\u6D3B\u52A8\u4E0D\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5
yami.group.prod.status.error=\u6D3B\u52A8\u5546\u54C1\u4E0D\u5728\u6B63\u5E38\u72B6\u6001
yami.group.prod.sold.out=\u6D3B\u52A8\u5546\u54C1\u89C4\u683C\u5DF2\u552E\u7A7A\u6216\u5DF2\u4E0B\u67B6
yami.group.prod.shop.limit=\u6D3B\u52A8\u5546\u54C1\u9650\u8D2D\u6570\u91CF\u4E3A
yami.group.user.shop.num=,\u60A8\u5DF2\u8D2D\u4E70
yami.group.user.now.shop=\u73B0\u8D2D
yami.group.prod.overstep.shop.limit=,\u8D85\u51FA\u6700\u5927\u7684\u8D2D\u4E70\u6570\u91CF
yami.group.prod.insufficient.stock=\u5E93\u5B58\u91CF\u4E0D\u8DB3\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u8D2D\u4E70\u6570\u91CF
yami.group.prod.has.group.order=\u60A8\u5DF2\u6709\u62FC\u56E2\u4E2D\u7684\u8BA2\u5355\uFF0C\u8BF7\u8010\u5FC3\u7B49\u5F85\u62FC\u56E2\u6210\u529F
yami.group.user.join.group=\u60A8\u6B63\u5728\u53C2\u52A0\u6B64\u6D3B\u52A8\uFF0C\u8BF7\u5728\u62FC\u56E2\u6210\u529F\u540E\u91CD\u8BD5
yami.group.user.join.check=\u5F53\u524D\u8BA2\u5355\u6B63\u5728\u7B49\u5F85\u6210\u56E2\u72B6\u6001\uFF0C\u9700\u7B49\u5F85\u6210\u56E2\u624D\u80FD\u8FDB\u884C\u4E0B\u4E00\u6B65\u64CD\u4F5C
yami.group.user.join.group.error=\u60A8\u5DF2\u53C2\u52A0\u8FC7\u6B64\u56E2\uFF0C\u4E0D\u80FD\u91CD\u590D\u53C2\u56E2
yami.group.order.no.exist=\u8BE5\u62FC\u56E2\u5355\u4E0D\u5B58\u5728
yami.request.too.much=\u8BF7\u6C42\u8FC7\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5
yami.day=\u5929
yami.constant.num=\u6B21
yami.seckill.order.expire=\u8BA2\u5355\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u5546\u54C1\u8FDB\u884C\u79D2\u6740
yami.seckill.complete=\u672C\u8F6E\u5546\u54C1\u5DF2\u88AB\u79D2\u6740\u5B8C\u6BD5\uFF0C\u8FD8\u6709\u7528\u6237\u672A\u652F\u4ED8\uFF0C\u8FD8\u6709\u673A\u4F1A\u54DF
yami.seckill.finish=\u672C\u5546\u54C1\u5DF2\u88AB\u79D2\u6740\u5B8C\u6BD5\uFF0C\u4E0B\u6B21\u8BB0\u5F97\u65E9\u70B9\u6765\u54DF
yami.seckill.limit.shop=\u672C\u6B21\u79D2\u6740\u5546\u54C1\u9650\u8D2D
yami.seckill.num=\u4EF6
yami.seckill.exception=\u79D2\u6740\u6D3B\u52A8\u672A\u5F00\u59CB\u6216\u5DF2\u7ED3\u675F
yami.seckill.not.start=\u79D2\u6740\u6D3B\u52A8\u672A\u5F00\u59CB
yami.seckill.has.ended=\u79D2\u6740\u6D3B\u52A8\u5DF2\u7ED3\u675F
yami.seckill.prod=\u5546\u54C1\u65E0\u6CD5\u53C2\u4E0E\u79D2\u6740\u6D3B\u52A8
yami.seckill.input.maxNum=\u8BF7\u8F93\u5165\u9650\u8D2D\u6570\u91CF
yami.seckill.cannot.delete=\u79D2\u6740\u6D3B\u52A8\u672A\u5173\u95ED\uFF0C\u65E0\u6CD5\u5220\u9664
yami.seckill.cannot.invalid=\u79D2\u6740\u6D3B\u52A8\u5DF2\u8FDD\u89C4\u4E0B\u67B6\uFF0C\u65E0\u6CD5\u5173\u95ED
yami.shop.cart.prod.unrecognized=\u8D2D\u7269\u8F66\u5305\u542B\u65E0\u6CD5\u8BC6\u522B\u7684\u5546\u54C1
yami.delivery.address=\u8BF7\u586B\u5199\u6536\u8D27\u5730\u5740
yami.product.remove=\u5546\u54C1\u5DF2\u4ECE\u8D2D\u7269\u8F66\u79FB\u9664
yami.station.address.check=\u8BF7\u586B\u5199\u81EA\u63D0\u4FE1\u606F
yami.station.detail.check=\u8BF7\u9009\u62E9\u81EA\u63D0\u70B9\u5E76\u586B\u5199\u5B8C\u6574\u7684\u81EA\u63D0\u4FE1\u606F
yami.station.no.find=\u672A\u627E\u5230\u8BE5\u81EA\u63D0\u70B9\u4FE1\u606F
yami.product.not.exist=\u67E5\u627E\u4E0D\u5230\u8BE5\u5546\u54C1\u4FE1\u606F
yami.product.off.not.enable.disProduct=\u5546\u54C1\u4E0D\u5904\u4E8E\u4E0A\u67B6\u72B6\u6001\uFF0C\u5206\u9500\u5546\u54C1\u4E0D\u80FD\u8FDB\u884C\u4E0A\u67B6\u64CD\u4F5C
yami.product.already.deleted=\u8BE5\u5546\u54C1\u5DF2\u7ECF\u88AB\u5220\u9664
yami.stock.no.number=\u5E93\u5B58\u5FC5\u987B\u4E3A\u7EAF\u6570\u5B57\u6574\u6570,\u4E14\u6700\u591A\u8F93\u51659\u4F4D\u6570\u5B57
yami.product.service.delete=\u5546\u54C1\u72B6\u6001\u4E0D\u6B63\u786E\uFF0C\u8BF7\u8054\u7CFB\u5E73\u53F0
yami.renovation.not.exist=\u67E5\u627E\u4E0D\u5230\u8BE5\u88C5\u4FEE\u4FE1\u606F
yami.unable.get.page=\u65E0\u6CD5\u83B7\u53D6\u9875\u9762\u4FE1\u606F
yami.product.off.shelves=\u5546\u54C1\u5DF2\u4E0B\u7EBF
yami.product.disable=\u5546\u54C1\u5DF2\u552E\u7A7A\u6216\u5DF2\u4E0B\u67B6
yami.product.on.normal=\u5546\u54C1\u4E0D\u5728\u6B63\u5E38\u72B6\u6001\uFF0C\u4FEE\u6539\u5931\u8D25
yami.insufficient.inventory=\u5E93\u5B58\u4E0D\u8DB3
yami.insufficient.inventory.place.new.order= \u5E93\u5B58\u4E0D\u8DB3, \u8BF7\u91CD\u65B0\u4E0B\u5355
yami.product=\u5546\u54C1
yami.selelct.items=\u8BF7\u9009\u62E9\u60A8\u9700\u8981\u7684\u5546\u54C1\u52A0\u5165\u8D2D\u7269\u8F66
yami.product.download=\u5F00\u59CB\u4E0B\u8F7D\u6A21\u677F
yami.product.dvy.type=\u8BF7\u9009\u62E9\u914D\u9001\u65B9\u5F0F
yami.product.dvy.fee=\u8FD0\u8D39\u4E0D\u80FD\u5C0F\u4E8E\u96F6
yami.product.group.check=\u7EC4\u5408\u5355\u54C1\u5FC5\u987B\u5173\u8054\u4E00\u4E2A\u5355\u54C1
yami.product.join.group=\u5546\u54C1\u6B63\u5728\u53C2\u4E0E\u62FC\u56E2\u6D3B\u52A8\uFF0C\u65E0\u6CD5\u4FEE\u6539\u89C4\u683C
yami.product.join.seckill=\u5546\u54C1\u6B63\u5728\u53C2\u4E0E\u79D2\u6740\u6D3B\u52A8\uFF0C\u65E0\u6CD5\u4FEE\u6539\u89C4\u683C
yami.product.signing.category.invalid=\u8BE5\u5546\u54C1\u7684\u7B7E\u7EA6\u5206\u7C7B\u5DF2\u5931\u6548\uFF0C\u65E0\u6CD5\u4FEE\u6539\u5546\u54C1\u72B6\u6001
yami.product.category.not.under=\u5F53\u524D\u5E73\u53F0\u5206\u7C7B\u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u5237\u65B0\u5206\u7C7B\u5217\u8868\u91CD\u65B0\u9009\u62E9
yami.product.category.not.exit=\u60A8\u5DF2\u53D6\u6D88\u4E0E\u8BE5\u5546\u54C1\u7C7B\u578B\u7684\u7B7E\u7EA6\uFF0C\u8BF7\u91CD\u65B0\u7B7E\u7EA6\u8BE5\u5546\u54C1\u7C7B\u578B\u65B9\u53EF\u4E0A\u67B6
yami.product.category.is.offline=\u8BE5\u5E73\u53F0\u5206\u7C7B\u5DF2\u88AB\u4E0B\u7EBF\uFF0C\u65E0\u6CD5\u4E0A\u67B6\u8BE5\u5546\u54C1
yami.product.shop.category.not.under=\u5F53\u524D\u5E97\u94FA\u5206\u7C7B\u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u5237\u65B0\u5206\u7C7B\u5217\u8868\u91CD\u65B0\u9009\u62E9
yami.product.brand.not.under=\u5F53\u524D\u9009\u62E9\u7684\u54C1\u724C\u5DF2\u7ECF\u4E0D\u80FD\u4F7F\u7528\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9
yami.product.brand.not.delete=\u6709\u90E8\u5206\u5546\u54C1\u5728\u4F7F\u7528\u8BE5\u54C1\u724C\uFF0C\u4E0D\u80FD\u8FDB\u884C\u5220\u9664\u64CD\u4F5C
yami.product.no.exist=\u5546\u54C1\u4FE1\u606F\u4E0D\u5B58\u5728
yami.product.no.auth=\u6CA1\u6709\u6743\u9650\u83B7\u53D6\u8BE5\u5546\u54C1\u89C4\u683C\u4FE1\u606F
yami.product.no.auth.update=\u6CA1\u6709\u6743\u9650\u4FEE\u6539\u6B64\u5546\u54C1
yami.product.category.offline=\u5E73\u53F0\u5206\u7C7B\u5904\u4E8E\u4E0B\u7EBF\u4E2D\uFF0C\u5546\u54C1\u4E0D\u80FD\u4E0A\u67B6\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u540E\u518D\u8FDB\u884C\u64CD\u4F5C
yami.product.shop.category.offline=\u672C\u5E97\u5206\u7C7B\u5904\u4E8E\u4E0B\u7EBF\u4E2D\uFF0C\u5546\u54C1\u4E0D\u80FD\u4E0A\u67B6
yami.product.shop.offline=\u5E97\u94FA\u5904\u4E8E\u8FDD\u89C4\u4E0B\u7EBF\u4E2D\uFF0C\u4E0D\u80FD\u8FDB\u884C\u6B64\u64CD\u4F5C\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u540E\u91CD\u8BD5
yami.product.shop.AUDIT=\u5E97\u94FA\u5BA1\u6838\u4E2D\uFF0C\u4E0D\u80FD\u8FDB\u884C\u6B64\u64CD\u4F5C\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u540E\u91CD\u8BD5
yami.product.enable.sku=\u81F3\u5C11\u8981\u542F\u7528\u4E00\u79CD\u5546\u54C1\u89C4\u683C
yami.same.specifications=\u5DF2\u6709\u76F8\u540C\u540D\u79F0\u89C4\u683C
yami.shop.name.have.already=\u5DF2\u6709\u76F8\u540C\u5E97\u94FA\u540D\u79F0
yami.shop.auditing=\u5E97\u94FA\u5BA1\u6838\u4E2D\uFF0C\u8BF7\u4E0D\u8981\u91CD\u590D\u63D0\u4EA4
yami.product.sold.out=\u5546\u54C1\u5DF2\u552E\u7A7A\u6216\u5DF2\u4E0B\u67B6
yami.order.expired=\u8BA2\u5355\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u4E0B\u5355
yami.add.live.prod.num=\u6DFB\u52A0\u5FAE\u4FE1\u76F4\u64AD\u95F4\u5546\u54C1\u5931\u8D25
yami.live.room.wechat.not.exist = \u5FAE\u4FE1\u76F4\u64AD\u63A7\u5236\u53F0\u4E0D\u5B58\u5728\u8BE5\u623F\u95F4
yami.live.prod.wechat.not.exist = \u5FAE\u4FE1\u76F4\u64AD\u63A7\u5236\u53F0\u4E0D\u5B58\u5728\u8BE5\u5546\u54C1
yami.category.one.check=\u4E00\u7EA7\u5206\u7C7B\u4E0D\u80FD\u6539\u4E3A\u4E8C\u7EA7\u5206\u7C7B
yami.category.two.check=\u4E8C\u7EA7\u5206\u7C7B\u4E0D\u80FD\u6539\u4E3A\u4E00\u7EA7\u5206\u7C7B
yami.category.superior.check=\u5206\u7C7B\u7684\u4E0A\u7EA7\u4E0D\u80FD\u662F\u81EA\u5DF1\u672C\u8EAB
yami.category.name.exist=\u7C7B\u76EE\u540D\u79F0\u5DF2\u5B58\u5728\uFF01
yami.category.status.check=\u4FEE\u6539\u5931\u8D25\uFF0C\u4E0A\u7EA7\u5206\u7C7B\u4E0D\u5B58\u5728\u6216\u8005\u4E0D\u4E3A\u6B63\u5E38\u72B6\u6001
yami.category.delete.check=\u8BE5\u5206\u7C7B\u4E0B\u8FD8\u6709\u5546\u54C1\uFF0C\u8BF7\u5148\u5220\u9664\u8BE5\u5206\u7C7B\u4E0B\u7684\u5546\u54C1
yami.category.delete.child=\u8BF7\u5220\u9664\u5B50\u5206\u7C7B\uFF0C\u518D\u5220\u9664\u8BE5\u5206\u7C7B
yami.distribution.has.distributionUser=\u8BE5\u7528\u6237\u5DF2\u5904\u4E8E\u4F7F\u7528\u4E2D\uFF0C\u8BF7\u52FF\u91CD\u590D\u4FEE\u6539
yami.score.select.num=\u8BF7\u9009\u62E9\u5546\u54C1
yami.score.select.num.shop=\u8BF7\u9009\u62E9\u60A8\u9700\u8981\u7684\u5546\u54C1\u8FDB\u884C\u8D2D\u4E70
yami.user.score.enough=\u7528\u6237\u79EF\u5206\u4E0D\u8DB3
yami.user.score.input.check=\u8BF7\u8F93\u5165\u6B63\u786E\u7684\u79EF\u5206\u6570\u91CF
yami.user.score.no.enough=\u79EF\u5206\u4E0D\u8DB3\u65E0\u6CD5\u63D0\u4EA4\u8BA2\u5355
yami.user.score.prod=\u4E0D\u662F\u79EF\u5206\u5546\u54C1\u6216\u8005\u79EF\u5206\u4EF7\u683C\u5F02\u5E38
yami.user.no.get.phone=\u65E0\u6CD5\u83B7\u53D6\u7528\u6237\u624B\u673A\u53F7\u4FE1\u606F
yami.user.account.error=\u7528\u6237\u540D\u6216\u5BC6\u7801\u4E0D\u6B63\u786E
yami.user.account.exist=\u7528\u6237\u540D\u5DF2\u5B58\u5728
yami.user.account.no.exist=\u7528\u6237\u4E0D\u5B58\u5728
yami.user.disabled = \u7528\u6237\u5DF2\u7981\u7528\uFF0C\u8BF7\u8054\u7CFB\u5BA2\u670D
yami.user.err.phone=\u8BF7\u8F93\u5165\u6B63\u786E\u7684\u624B\u673A\u53F7
yami.user.account.lock=\u8D26\u53F7\u5DF2\u88AB\u9501\u5B9A,\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458
yami.user.account.lock.pre=\u8D26\u53F7\u5DF2\u88AB\u9501\u5B9A\uFF0C\u539F\u56E0\u662F\uFF1A
yami.user.account.lock.after=\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458
yami.user.phone.exist=\u8BE5\u624B\u673A\u53F7\u5DF2\u6CE8\u518C\uFF0C\u65E0\u6CD5\u91CD\u65B0\u6CE8\u518C
yami.user.name.check=\u7528\u6237\u540D\u5E94\u75314-16\u4F4D\u6570\u5B57\u5B57\u6BCD\u4E0B\u5212\u7EBF\u7EC4\u6210
yami.user.password.no.exist=\u65B0\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
yami.user.password.check=\u65B0\u5BC6\u7801\u4E0D\u80FD\u4E0E\u539F\u5BC6\u7801\u76F8\u540C!
yami.user.code.error=\u9A8C\u8BC1\u7801\u6709\u8BEF\u6216\u5DF2\u8FC7\u671F
yami.user.code.empty=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A
yami.user.code.check.too.much=\u9A8C\u8BC1\u7801\u6821\u9A8C\u8FC7\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5
yami.verification.limit=\u4ECA\u65E5\u53D1\u9001\u77ED\u4FE1\u9A8C\u8BC1\u7801\u6B21\u6570\u5DF2\u8FBE\u5230\u4E0A\u9650
yami.verification.time.check=\u4E00\u5206\u949F\u5185\u53EA\u80FD\u53D1\u9001\u4E00\u6B21\u9A8C\u8BC1\u7801
yami.verification.expire=\u9A8C\u8BC1\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u9A8C\u8BC1\u7801\u6821\u9A8C
yami.sending.message.failed=\u53D1\u9001\u77ED\u4FE1\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5
yami.user.login.error=\u767B\u9646\u4FE1\u606F\u5F02\u5E38
yami.user.login.type=\u65E0\u6CD5\u83B7\u53D6\u767B\u9646\u65B9\u5F0F
yami.user.unable.login.type=\u672A\u5B9E\u73B0\u8BE5\u767B\u9646\u65B9\u6CD5
yami.user.no.exist=\u65E0\u6CD5\u83B7\u53D6\u7528\u6237\u4FE1\u606F
yami.select.source=\u8BF7\u9009\u62E9\u7D20\u6750\u7C7B\u578B
yami.user.level.no.exist=\u4F1A\u5458\u7B49\u7EA7\u4E0D\u5B58\u5728\u6216\u5F53\u524D\u7B49\u7EA7\u4E0D\u4E3A\u4ED8\u8D39\u4F1A\u5458\u7B49\u7EA7
yami.user.pay.level.check=\u7528\u6237\u65E0\u6CD5\u5728\u4F1A\u5458\u671F\u95F4\u8D2D\u4E70\u4F4E\u7B49\u7EA7\u4F1A\u5458
yami.user.growh.no.enough=\u7528\u6237\u6210\u957F\u503C\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u8D2D\u4E70
yami.user.request.error=\u7528\u6237\u76F8\u5173\u7684\u8BF7\u6C42\uFF0C\u5E94\u8BE5\u4EE5/p\u5F00\u5934\uFF01\uFF01\uFF01
yami.user.addr.update.error=\u65E0\u6CD5\u4FEE\u6539\u7528\u6237\u9ED8\u8BA4\u5730\u5740\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5
yami.user.level.delete.error=\u6B64\u7B49\u7EA7\u4E0D\u80FD\u5220\u9664\uFF0C\u5FC5\u987B\u8981\u4FDD\u7559\u6700\u5C11\u4E00\u4E2A\u7B49\u7EA7
yami.user.level.update.repeatLevelName.error=\u76F8\u540C\u4F1A\u5458\u7C7B\u578B\u7684\u7B49\u7EA7\u540D\u79F0\u4E0D\u80FD\u91CD\u590D
yami.shop.user.account.lock=\u8D26\u53F7\u5DF2\u88AB\u9501\u5B9A,\u8BF7\u8054\u7CFB\u5E97\u94FA\u7BA1\u7406\u5458
yami.shop.sys.super.user.no.modify=\u5E97\u94FA\u8D85\u7EA7\u7BA1\u7406\u5458\uFF0C\u4E0D\u80FD\u5728\u6B64\u5904\u66F4\u6539
yami.shop.account.have.only.one=\u4E00\u4E2A\u5E97\u94FA\u9700\u8981\u4EC5\u4E00\u4E2A\u8D85\u7EA7\u7BA1\u7406\u5458\uFF0C\u8BF7\u5904\u7406\u5E97\u94FA\u8D26\u53F7\u6570\u636E
yami.shop.data.is.removed=\u6B64\u6570\u636E\u5DF2\u88AB\u5220\u9664
yami.shop.card.is.exist=\u8BE5\u94F6\u884C\u5361\u53F7\u5DF2\u5B58\u5728
yami.discount.MaxReduceAmount.limit=\u8BF7\u8F93\u5165\u4E00\u4E2A\u5C0F\u4E8E10\u768413\u6B21\u65B9\u7684\u6570\u5B57
yami.distribution.close=\u63A8\u5E7F\u8BA1\u5212\u5DF2\u5173\u95ED
yami.distribution.set.exception=\u5206\u9500\u8BBE\u7F6E\u5F02\u5E38\
yami.distribution.userWallet.banlance=\u60A8\u7684\u5206\u9500\u8D26\u6237\u4F59\u989D\u5927\u4E8E0
yami.distribution.info.cardno=\u7533\u8BF7\u586B\u5199\u4FE1\u606F\u4E0D\u5168,\u9700\u8981\u8EAB\u4EFD\u8BC1\u53F7
yami.distribution.info.pic=\u7533\u8BF7\u586B\u5199\u4FE1\u606F\u4E0D\u5168,\u9700\u8981\u8EAB\u4EFD\u8BC1\u7167\u7247
yami.distribution.info.name=\u7533\u8BF7\u586B\u5199\u4FE1\u606F\u4E0D\u5168,\u9700\u8981\u771F\u5B9E\u59D3\u540D
yami.distribution.submit.examine=\u4F60\u5DF2\u7ECF\u63D0\u4EA4\u8FC7\u5BA1\u6838\u4E86,\u8BF7\u8010\u5FC3\u7B49\u5F85
yami.distribution.ban.examine=\u8BE5\u8D26\u6237\u5DF2\u88AB\u6C38\u4E45\u5C01\u7981
yami.distribution.clear.examine=\u5DF2\u6682\u65F6\u5C01\u7981\u4E0D\u53EF\u7533\u8BF7,\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458
yami.distribution.success.examine=\u4F60\u7684\u5BA1\u6838\u5DF2\u7ECF\u901A\u8FC7,\u65E0\u9700\u518D\u6B21\u5BA1\u6838
yami.distribution.get.examine=\u65E0\u6CD5\u83B7\u53D6\u9080\u8BF7\u4EBA\u4FE1\u606F
yami.distribution.shop.error=\u9080\u8BF7\u4EBA\u5E97\u94FA\u4FE1\u606F\u6709\u8BEF
yami.distribution.user.error=\u81EA\u5DF1\u65E0\u6CD5\u9080\u8BF7\u81EA\u5DF1
yami.distribution.user.Unqualified=\u4E0D\u7B26\u5408\u7533\u8BF7\u6761\u4EF6\uFF0C\u8BF7\u8054\u7CFB\u5BA2\u670D\u8FDB\u884C\u7533\u8BF7
yami.distribution.fee.error=\u6D88\u8D39\u91D1\u989D\u4E0D\u7B26\u5408\u8981\u6C42
yami.distribution.fee.num=\u6D88\u8D39\u7B14\u6570\u4E0D\u7B26\u5408\u8981\u6C42
yami.distribution.user.no.shop=\u60A8\u8FD8\u4E0D\u662F\u672C\u5E97\u7684\u5206\u9500\u5458
yami.distribution.user.no.distributor=\u60A8\u8FD8\u4E0D\u662F\u5206\u9500\u5458
yami.distribution.user.no.distributor1=\u60A8\u7684\u5206\u9500\u8EAB\u4EFD\u5F02\u5E38\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458
yami.distribution.no.distributor=\u4F60\u8FD8\u4E0D\u662F\u5206\u9500\u5458\uFF0C\u65E0\u6CD5\u8FDB\u884C\u5347\u7EA7\u64CD\u4F5C
yami.distribution.level.limit=\u5DF2\u8FBE\u5230\u7B49\u7EA7\u4E0A\u9650
yami.distribution.level.condition=\u60A8\u4E0D\u7B26\u5408\u5347\u7EA7\u6761\u4EF6
yami.distribution.cash.param1=\u63D0\u73B0\u91D1\u989D\u4E0D\u80FD\u4E3A\u7A7A
yami.distribution.cash.param2=\u6700\u5C0F\u63D0\u73B0\u91D1\u989D\u4E3A1\u5143
yami.distribution.cash.num=\u63D0\u73B0\u6B21\u6570\u4E3A
yami.distribution.cash.month=\u6BCF\u6708
yami.distribution.set.error=\u672A\u627E\u5230\u8BE5\u5E97\u94FA\u5206\u9500\u57FA\u7840\u8BBE\u7F6E\u4FE1\u606F
yami.distribution.prod.exist.error=\u672A\u627E\u5230\u8BE5\u5206\u9500\u5546\u54C1\u4FE1\u606F
yami.distribution.prod.award=\u56FA\u5B9A\u5956\u52B1\u6BD4\u4F8B\u8BBE\u7F6E\u4E0D\u80FD\u8D85\u8FC7100%
yami.distribution.prod.level=\u7B49\u7EA7\u5956\u52B1\u6BD4\u4F8B\u8BBE\u7F6E\u4E0D\u80FD\u8D85\u8FC7100%
yami.distribution.prod.award.check=\u56FA\u5B9A\u5956\u52B1\u8BBE\u7F6E\u4E0D\u80FD\u8D85\u8FC7\u5546\u54C1\u7684\u6700\u9AD8\u4EF7
yami.distribution.prod.level.check=\u7B49\u7EA7\u5956\u52B1\u8BBE\u7F6E\u4E0D\u80FD\u8D85\u8FC7\u5546\u54C1\u7684\u6700\u9AD8\u4EF7
yami.distribution.prod.parent.award=\u9080\u8BF7\u4EBA\u56FA\u5B9A\u5956\u52B1\u6BD4\u4F8B\u8BBE\u7F6E\u4E0D\u80FD\u8D85\u8FC7100%
yami.distribution.prod.parent.level=\u9080\u8BF7\u4EBA\u7B49\u7EA7\u5956\u52B1\u6BD4\u4F8B\u8BBE\u7F6E\u4E0D\u80FD\u8D85\u8FC7100%
yami.distribution.prod.parentAward.check=\u9080\u8BF7\u4EBA\u56FA\u5B9A\u5956\u52B1\u4E0D\u80FD\u5927\u4E8E\u6216\u7B49\u4E8E\u5546\u54C1\u7684\u6700\u9AD8\u4EF7
yami.distribution.prod.parentLevel.check=\u9080\u8BF7\u4EBA\u7B49\u7EA7\u5956\u52B1\u4E0D\u80FD\u5927\u4E8E\u6216\u7B49\u4E8E\u5546\u54C1\u7684\u6700\u9AD8\u4EF7
yami.distribution.prod.price.check=\u5956\u52B1\u8BBE\u7F6E\u4E0D\u80FD\u5927\u4E8E\u7B49\u4E8E\u5546\u54C1\u6700\u9AD8\u4EF7\u6216\u8005\u6BD4\u4F8B100%
yami.distribution.prod.exist=\u5206\u9500\u5546\u54C1\u5DF2\u7ECF\u5B58\u5728
yami.distribution.exist.error=\u672A\u627E\u5230\u5206\u9500\u5458\u4FE1\u606F
yami.distribution.enable.error=\u5546\u6237\u672A\u5F00\u542F\u8BE5\u7ED1\u5B9A\u7528\u6237\u65B9\u5F0F
yami.distribution.extension.error=\u60A8\u5DF2\u6210\u4E3A\u8BE5\u5E97\u94FA\u7684\u63A8\u5E7F\u5458\uFF0C\u65E0\u6CD5\u88AB\u63A8\u5E7F
yami.distribution.extension.time=\u60A8\u8FD8\u5728\u63A8\u5E7F\u671F\u5185\uFF0C\u65E0\u6CD5\u88AB\u65B0\u63A8\u5E7F\u5458\u63A8\u5E7F
yami.distribution.user.protection.period=\u7528\u6237\u5728\u4FDD\u62A4\u671F\u5185\uFF0C\u7ED1\u5B9A\u5931\u8D25
yami.distribution.status.error=\u63A8\u5E7F\u5458\u72B6\u6001\u5F02\u5E38
yami.distribution.get.fail=\u83B7\u53D6\u63A8\u5E7F\u5458\u4FE1\u606F\u5931\u8D25
yami.distribution.batch.update.income=\u6279\u91CF\u66F4\u65B0\u5206\u9500\u6536\u5165\u72B6\u6001\u5931\u8D25
yami.distribution.fee.than.error=\u63D0\u73B0\u91D1\u989D\u5927\u4E8E\u6700\u5927\u63D0\u73B0\u91D1\u989D
yami.distribution.fee.less.error=\u63D0\u73B0\u91D1\u989D\u5C0F\u4E8E\u6700\u5C0F\u63D0\u73B0\u91D1\u989D
yami.distribution.user.withdrawals=\u60A8\u672A\u7ED1\u5B9A\u5FAE\u4FE1\uFF0C\u8BF7\u5148\u5728\u5FAE\u4FE1\u5C0F\u7A0B\u5E8F\u6388\u6743\u767B\u5F55\u540E\u518D\u63D0\u73B0
yami.distribution.balance.not.enough=\u63D0\u73B0\u5931\u8D25,\u4F59\u989D\u4E0D\u8DB3
yami.sys.menu.exist=\u83DC\u5355URL\u4E0D\u80FD\u4E3A\u7A7A
yami.sys.file.no.exist=\u672A\u914D\u7F6E\u6587\u4EF6\u57DF\u540D\uFF0C\u65E0\u6CD5\u4E0A\u4F20\u6210\u529F\u56FE\u7247
yami.sys.sms.no.exist=\u65E0\u6CD5\u83B7\u53D6\u77ED\u4FE1\u914D\u7F6E\uFF0C\u65E0\u6CD5\u53D1\u9001\u77ED\u4FE1
yami.sys.wxMa.no.exist=\u8BF7\u5728\u540E\u53F0\u9875\u9762\u8BBE\u7F6E\u5FAE\u4FE1\u5C0F\u7A0B\u5E8F\u4FE1\u606F\u540E\uFF0C\u518D\u8FDB\u884C\u64CD\u4F5C
yami.sys.wxMp.no.exist=\u8BF7\u5728\u540E\u53F0\u9875\u9762\u8BBE\u7F6E\u5FAE\u4FE1\u516C\u4F17\u53F7\u4FE1\u606F\u540E\uFF0C\u518D\u8FDB\u884C\u64CD\u4F5C
yami.sys.wxApp.no.exist=\u8BF7\u5728\u540E\u53F0\u9875\u9762\u8BBE\u7F6E\u5FAE\u4FE1\u5F00\u653E\u5E73\u7533\u8BF7\u5E94\u7528\u76F8\u5173\u4FE1\u606F\u540E\uFF0C\u518D\u8FDB\u884C\u64CD\u4F5C
yami.sys.wxPay.no.exist=\u8BF7\u5728\u540E\u53F0\u9875\u9762\u8BBE\u7F6E\u5FAE\u4FE1\u652F\u4ED8\u4FE1\u606F\u540E\uFF0C\u518D\u8FDB\u884C\u64CD\u4F5C
yami.sys.wxDomain.no.exist=\u8BF7\u5728\u540E\u53F0\u9875\u9762\u8BBE\u7F6E\u56DE\u8C03\u57DF\u540D\u540E\uFF0C\u518D\u8FDB\u884C\u64CD\u4F5C
yami.sys.menu.child.delete=\u8BF7\u5148\u5220\u9664\u5B50\u83DC\u5355\u6216\u6309\u94AE
yami.sys.menu.delete.error=\u7CFB\u7EDF\u83DC\u5355\uFF0C\u4E0D\u80FD\u5220\u9664
yami.sys.menu.user.error=\u81EA\u5DF1\u4E0D\u80FD\u662F\u81EA\u5DF1\u7684\u4E0A\u7EA7
yami.sys.menu.superior.list=\u4E0A\u7EA7\u83DC\u5355\u53EA\u80FD\u4E3A\u76EE\u5F55\u7C7B\u578B
yami.sys.menu.superior.menu=\u4E0A\u7EA7\u83DC\u5355\u53EA\u80FD\u4E3A\u83DC\u5355\u7C7B\u578B
yami.sys.role.identical.name=\u7CFB\u7EDF\u5DF2\u5B58\u5728\u76F8\u540C\u89D2\u8272\u540D\u79F0
yami.document.no.content=\u6587\u4EF6\u65E0\u5185\u5BB9
yami.file.error=\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF
yami.modified.settlement.information=\u7ED3\u7B97\u4FE1\u606F\u5DF2\u66F4\u6539
yami.platform.num.check=\u5E73\u53F0\u4ECA\u65E5
yami.num.limit=\u53EF\u7528\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650!
yami.sys.delete.error=\u5F53\u524D\u7528\u6237\u4E0D\u80FD\u5220\u9664
yami.sys.admin.error=\u7CFB\u7EDF\u7BA1\u7406\u5458\u4E0D\u80FD\u5220\u9664
yami.sys.select.user=\u8BF7\u9009\u62E9\u9700\u8981\u5220\u9664\u7684\u7528\u6237
yami.sys.user.already=\u8BE5\u7528\u6237\u540D\u5DF2\u5B58\u5728
yami.sys.sms.package=\u8D2D\u4E70\u7684\u77ED\u4FE1\u5957\u9910\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5
yami.sys.sms.package.limit=\u5957\u9910\u5305\u6570\u91CF\u5DF2\u8FBE\u4E0A\u9650\u5341\u4E2A\uFF0C\u8BF7\u8FDB\u884C\u5220\u9664\u540E\u518D\u6DFB\u52A0\uFF01
yami.sys.illegalArgument=\u8BF7\u6C42\u53C2\u6570\u975E\u6CD5\uFF0C\u8BF7\u6838\u5B9E!
yami.cannot.get.app.info=\u65E0\u6CD5\u83B7\u53D6app\u4FE1\u606F
yami.same.key=\u7CFB\u7EDF\u5DF2\u5B58\u5728\u76F8\u540C\u914D\u7F6E\u7684key
yami.sys.paypal.no.exist=\u8BF7\u5728\u540E\u53F0\u9875\u9762\u8BBE\u7F6Epaypal\u76F8\u5173\u4FE1\u606F\u540E\uFF0C\u518D\u8FDB\u884C\u64CD\u4F5C
yami.address.deleted=\u8BA2\u5355\u9879\u4E0D\u5B58\u5728
yami.item.has.commented=\u8BE5\u8BA2\u5355\u9879\u5DF2\u8BC4\u8BBA\uFF0C\u8BF7\u52FF\u91CD\u590D\u8BC4\u8BBA
yami.item.com.repeated==\u8BA2\u5355\u8BC4\u8BBA\u5DF2\u63D0\u4EA4
yami.confirm.receipt=\u8BF7\u786E\u8BA4\u6536\u8D27\u540E\u518D\u8FDB\u884C\u8BC4\u8BBA
yami.comment.is.delete=\u8BC4\u4EF7\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5220\u9664\uFF0C\u8BF7\u8FD4\u56DE\u540E\u5237\u65B0\u91CD\u8BD5
yami.cannot.reapply=\u60A8\u5DF2\u7ECF\u7533\u8BF7\u5F00\u542F\u5E97\u94FA,\u4E0D\u80FD\u91CD\u65B0\u7533\u8BF7
yami.shop.num.check=\u5E97\u94FA\u4ECA\u65E5
yami.store.name.exist=\u5E97\u94FA\u540D\u79F0\u5DF2\u5B58\u5728
yami.store.not.exist=\u672A\u627E\u5230\u5E97\u94FA\u4FE1\u606F
yami.shop.not.category=\u5F53\u524D\u5E97\u94FA\u6CA1\u6709\u7B7E\u7EA6\u7684\u5E73\u53F0\u5206\u7C7B\uFF0C\u8BF7\u5148\u7B7E\u7EA6\u5206\u7C7B
yami.station.account.exist=\u6B64\u8D26\u53F7\u5DF2\u5B58\u5728\uFF0C\u8BF7\u8F93\u5165\u65B0\u7684\u8D26\u53F7
yami.store.account.exist=\u8BE5\u8D26\u53F7\u5DF2\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165
yami.store.apply.no.exist=\u672A\u627E\u5230\u7533\u8BF7\u4FE1\u606F
yami.store.offline.check=\u5E97\u94FA\u4E0D\u5904\u4E8E\u8425\u4E1A\u6216\u505C\u4E1A\u72B6\u6001,\u4E0D\u80FD\u8FDB\u884C\u4E0B\u7EBF
yami.shop.company.repeat.application=\u4E0D\u80FD\u540C\u65F6\u63D0\u4EA4\u591A\u6B21\u53D8\u66F4\u7533\u8BF7\uFF0C\u8BF7\u8010\u5FC3\u7B49\u5019\u5E73\u53F0\u5BA1\u6838\uFF0C\u6216\u8005\u628A\u5DF2\u6709\u7533\u8BF7\u64A4\u9500\u540E\u91CD\u65B0\u7533\u8BF7
yami.cannot.update.wallet=\u66F4\u65B0\u5E97\u94FA\u94B1\u5305\u4FE1\u606F\u5931\u8D25
yami.cannot.distribution.update.wallet=\u66F4\u65B0\u63A8\u5E7F\u5458\u94B1\u5305\u4FE1\u606F\u5931\u8D25
yami.store.brand.name.error=\u8BE5\u54C1\u724C\u540D\u79F0\u5DF2\u5B58\u5728
yami.my.store.no.cash=\u81EA\u8425\u5E97\u65E0\u6CD5\u63D0\u73B0
yami.shop.cash.too.less=\u63D0\u73B0\u91D1\u989D\u4E0D\u80FD\u5C11\u4E8E1.00\u5143
yami.shop.cannot.delete.card=\u4E0D\u80FD\u5220\u9664\u9ED8\u8BA4\u94F6\u884C\u5361
yami.shop.max.card.num=\u94F6\u884C\u5361\u5DF2\u8FBE\u5230\u6700\u5927\u6570\u91CF\uFF0C\u4E0D\u80FD\u518D\u65B0\u589E
yami.shop.least.one.card=\u81F3\u5C11\u4FDD\u7559\u4E00\u5F20\u94F6\u884C\u5361
yami.shop.cannot.delete.check=\u6B63\u5728\u7528\u4E8E\u7533\u8BF7\u63D0\u73B0\u7684\u94F6\u884C\u5361\u4E0D\u80FD\u5220\u9664
yami.shop.station.close=\u8BE5\u81EA\u63D0\u70B9\u5DF2\u5173\u95ED\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458
yami.shop.station.not.open=\u8BE5\u81EA\u63D0\u70B9\u672A\u5728\u8425\u4E1A\u72B6\u6001
yami.shop.phone.no.exist=\u624B\u673A\u53F7\u4E0D\u80FD\u4E3A\u7A7A
yami.shop.update.balance=\u66F4\u65B0\u4F59\u989D\u8BB0\u5F55\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5
yami.shop.cash.no.enough=\u53EF\u63D0\u73B0\u91D1\u989D\u4E0D\u8DB3
yami.shop.cash.grant=\u5546\u5BB6\u63D0\u73B0\u53D1\u653E
yami.shop.company.credit.code.repeat=\u7EDF\u4E00\u4FE1\u7528\u7801\u91CD\u590D
yami.shop.business.date.error=\u8425\u4E1A\u8D77\u59CB\u65E5\u671F\u4E0D\u80FD\u5927\u4E8E\u7B49\u4E8E\u8425\u4E1A\u7EC8\u6B62\u65F6\u95F4
yami.shop.company.date.not.empty=\u8425\u4E1A\u65E5\u671F\u4E0D\u80FD\u4E3A\u7A7A
yami.shop.bank.card.not.empty=\u81F3\u5C11\u8981\u6DFB\u52A0\u4E00\u4E2A\u94F6\u884C\u5361
yami.shop.bank.card.no.repeat=\u8D26\u53F7\u91CD\u590D
yami.cash.grant=\u63D0\u73B0\u53D1\u653E
yami.open.store=\u8BF7\u5148\u8FDB\u884C\u5F00\u5E97\u7533\u8BF7
yami.password.error=\u539F\u5BC6\u7801\u4E0D\u6B63\u786E
yami.stop.cannot.modified=\u5E97\u94FA\u8D26\u53F7\u5DF2\u8BBE\u7F6E\u4E0D\u80FD\u4FEE\u6539
yami.stop.examine.success=\u5546\u5BB6\u5DF2\u7ECF\u5BA1\u6838\u6210\u529F\uFF0C\u65E0\u9700\u518D\u6B21\u5BA1\u6838
yami.stop.cannot.open=\u8BE5\u8D26\u53F7\u5DF2\u7ECF\u5F00\u901A\u8FC7\u5E97\u94FA\uFF0C\u65E0\u6CD5\u91CD\u590D\u5F00\u901A
yami.sign.check=\u9A8C\u7B7E\u5931\u8D25
yami.bar.code.exist=\u5355\u54C1\u6761\u7801\u5DF2\u7ECF\u5B58\u5728
yami.select.only.shop.type=\u8BF7\u9009\u62E9\u4E00\u4E2A\u5E97\u94FA\u7C7B\u578B
yami.select.a.shop=\u8BF7\u9009\u62E9\u4E00\u4E2A\u5E97\u94FA
yami.transaction.not.exists=\u4EA4\u6613\u5355\u53F7\u4E0D\u5B58\u5728
yami.query.error=\u67E5\u8BE2\u51FA\u9519
yami.order.no.exist=\u8BA2\u5355\u4E0D\u5B58\u5728
yami.order.is.delivery=\u8BE5\u8BA2\u5355\u5DF2\u6709\u90E8\u5206\u5546\u54C1\u53D1\u8D27\uFF0C\u65E0\u6CD5\u8FDB\u884C\u6279\u91CF\u53D1\u8D27\u64CD\u4F5C
yami.order.amount.error=\u8BA2\u5355\u91D1\u989D\u6709\u8BEF\uFF0C\u65E0\u6CD5\u8FDB\u884C\u652F\u4ED8
yami.order.amount.too.large.error=\u8BA2\u5355\u91D1\u989D\u8FC7\u5927\uFF0C\u65E0\u6CD5\u8FDB\u884C\u652F\u4ED8
yami.order.code.no.exist=\u8BE5\u6838\u9500\u7801\uFF0C\u6CA1\u6709\u5BF9\u5E94\u7684\u8BA2\u5355
yami.order.code.no.error=\u6838\u9500\u7801\u9519\u8BEF
yami.h5.index.ad.images.limit=\u8F6E\u64AD\u56FE\u4E0D\u80FD\u8D85\u8FC710\u4E2A
yami.order.payed=\u8BA2\u5355\u5DF2\u652F\u4ED8\uFF0C\u65E0\u6CD5\u53D6\u6D88\u8BA2\u5355
yami.order.not.paid=\u5F53\u524D\u8BA2\u5355\u8FD8\u672A\u4ED8\u6B3E\uFF0C\u65E0\u6CD5\u7533\u8BF7
yami.order.has.failed=\u5F53\u524D\u8BA2\u5355\u5DF2\u5931\u8D25\uFF0C\u4E0D\u5141\u8BB8\u9000\u6B3E
yami.order.receipt.no.delivery=\u8BA2\u5355\u672A\u53D1\u8D27\uFF0C\u65E0\u6CD5\u786E\u8BA4\u6536\u8D27
yami.order.pay.user.disable=\u60A8\u5DF2\u88AB\u7981\u7528\uFF0C\u4E0D\u80FD\u8D2D\u4E70\uFF0C\u8BF7\u8054\u7CFB\u5E73\u53F0\u5BA2\u670D
yami.order.status.no.right=\u8BA2\u5355\u4E0D\u5904\u4E8E\u5F85\u5165\u5E93\u72B6\u6001\uFF0C\u65E0\u6CD5\u8FDB\u884C\u5165\u5E93
yami.order.delivery.no.right=\u8BA2\u5355\u4E0D\u5904\u4E8E\u5F85\u53D1\u8D27\u72B6\u6001\uFF0C\u65E0\u6CD5\u8FDB\u884C\u53D1\u8D27
yami.order.no.delivery=\u8BA2\u5355\u4E0D\u5904\u4E8E\u5F85\u6536\u8D27\u72B6\u6001\uFF0C\u65E0\u6CD5\u786E\u8BA4\u6536\u8D27
yami.order.pay.fail=\u652F\u4ED8\u5931\u8D25\uFF0C\u8BA2\u5355\u4E0D\u5728\u672A\u652F\u4ED8\u72B6\u6001
yami.order.delivery.refund.error=\u8BE5\u8BA2\u5355\u6709\u9000\u6B3E\u4FE1\u606F\u6B63\u5728\u5904\u7406\u5F53\u4E2D\uFF0C\u8BF7\u5904\u7406\u5B8C\u6BD5\u4E4B\u540E\u518D\u8FDB\u884C\u53D1\u8D27\u7684\u64CD\u4F5C\uFF01
yami.order.receipt.refund=\u8BA2\u5355\u9000\u6B3E\u4E2D\uFF0C\u65E0\u6CD5\u786E\u8BA4\u6536\u8D27
yami.order.no.success=\u8BA2\u5355\u9000\u6B3E\u4E2D\uFF0C\u8BA2\u5355\u672A\u5B8C\u6210\u6216\u672A\u5173\u95ED\uFF0C\u65E0\u6CD5\u5220\u9664\u8BA2\u5355
yami.order.no.dvyName=\u5FEB\u9012\u516C\u53F8\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
yami.order.delivery.number=\u5FEB\u9012\u5355\u53F7\u683C\u5F0F\u9519\u8BEF
yami.order.delivery.error=\u591A\u5BB6\u5E97\u94FA\u63D0\u4EA4\u8BA2\u5355\u65F6\uFF0C\u914D\u9001\u65B9\u5F0F\u53EA\u80FD\u662F\u5FEB\u9012
yami.order.same.city.error=\u5F53\u524D\u5E97\u94FA\u672A\u5F00\u542F\u540C\u57CE\u914D\u9001!
yami.order.same.city.error2=\u8D85\u51FA\u5546\u5BB6\u914D\u9001\u8DDD\u79BB\u6216\u8D77\u9001\u8D39\u4E0D\u591F!
yami.order.same.city.error3=\u5F53\u524D\u8BA2\u5355\u4E0D\u652F\u6301\u540C\u57CE\u914D\u9001!
yami.order.same.city.error4=\u8D85\u51FA\u5F53\u524D\u8BBE\u7F6E\u7684\u914D\u9001\u8DDD\u79BB!
yami.order.unrecognized.prod=\u8BA2\u5355\u72B6\u6001\u5F02\u5E38\uFF0C\u65E0\u6CD5\u66F4\u6539\u8BA2\u5355\u5730\u5740
yami.order.unrecognized.update=\u8BA2\u5355\u72B6\u6001\u5F02\u5E38\uFF0C\u65E0\u6CD5\u66F4\u6539\u8BA2\u5355\u91D1\u989D
yami.order.amount.check=\u8BA2\u5355\u91D1\u989D\u5FC5\u987B\u5927\u4E8E0\uFF0C\u6216\u8005\u6570\u636E\u53D1\u751F\u53D8\u5316(\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5)
yami.order.status.error=\u8BA2\u5355\u5305\u542B\u65E0\u6CD5\u8BC6\u522B\u7684\u5546\u54C1
yami.order.status.change=\u8BA2\u5355\u72B6\u6001\u5DF2\u7ECF\u53D1\u751F\u6539\u53D8\uFF0C\u8BF7\u52FF\u91CD\u590D\u64CD\u4F5C
yami.order.status.check.change=\u8BA2\u5355\u72B6\u6001\u5DF2\u7ECF\u53D1\u751F\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u4E0B\u5355
yami.order.submit.change=\u8BF7\u52FF\u91CD\u590D\u63D0\u4EA4\u8BA2\u5355
yami.order.refund.status.exist=\u9000\u8D27\u72B6\u6001\u4E0D\u80FD\u4E3A\u7A7A
yami.order.refund.exist=\u9000\u6B3E\u5355\u4E0D\u5B58\u5728
yami.order.refund.define=\u8BF7\u5148\u786E\u5B9A\u9000\u6B3E\uFF0C\u624D\u80FD\u53D1\u8D77\u9000\u6B3E\u64CD\u4F5C
yami.order.refund.success=\u5DF2\u9000\u6B3E\u6210\u529F\uFF0C\u65E0\u6CD5\u518D\u7533\u8BF7\u9000\u6B3E\u64CD\u4F5C
yami.order.refund.cancel=\u4E70\u5BB6\u5DF2\u53D6\u6D88\u7533\u8BF7
yami.set.refund.information=\u8BF7\u9009\u62E9\u9000\u8D27\u5730\u5740
yami.order.refund.day.check=\u5F53\u524D\u8BA2\u5355\u5DF2\u786E\u8BA4\u6536\u8D27\u8D85\u8FC7
yami.order.refund.day.check2=\u5929\uFF0C\u65E0\u6CD5\u9000\u6B3E
yami.no.found.order=\u672A\u627E\u5230\u8BE5\u8BA2\u5355\u4FE1\u606F
yami.order.refund.score=\u79EF\u5206\u5546\u54C1\uFF0C\u65E0\u6CD5\u9000\u6B3E
yami.availabl.cash.refund=\u60A8\u7684\u53EF\u63D0\u73B0\u91D1\u989D\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u8FDB\u884C\u9000\u6B3E
yami.not.sufficient.refund=\u60A8\u7684\u5F85\u7ED3\u7B97\u91D1\u989D\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u8FDB\u884C\u9000\u6B3E
yami.refund.processed=\u9000\u6B3E\u5DF2\u5904\u7406\uFF0C\u65E0\u9700\u91CD\u590D\u5904\u7406
yami.order.all.refund.go.on=\u8BE5\u8BA2\u5355\u5DF2\u6709\u5546\u54C1\u6B63\u5728\u9000\u6B3E\u4E2D\uFF0C\u4E0D\u80FD\u518D\u8FDB\u884C\u6574\u5355\u9000\u6B3E
yami.order.all.refund.check=\u8BE5\u8BA2\u5355\u6B63\u5728\u8FDB\u884C\u6574\u5355\u9000\u6B3E\uFF0C\u65E0\u6CD5\u8FDB\u884C\u65B0\u7684\u9000\u6B3E\u64CD\u4F5C
yami.order.need.station=\u8BF7\u9009\u62E9\u6700\u5C11\u4E00\u4E2A\u9700\u8981\u81EA\u63D0\u7684\u8BA2\u5355
yami.order.refund.go.on=\u8BE5\u5546\u54C1\u6B63\u5728\u8FDB\u884C\u9000\u6B3E\u4E2D\uFF0C\u65E0\u6CD5\u8FDB\u884C\u65B0\u7684\u9000\u6B3E\u64CD\u4F5C
yami.refund.exceeded.amount=\u9000\u6B3E\u91D1\u989D\u5DF2\u8D85\u51FA\u8BA2\u5355\u91D1\u989D\uFF0C\u65E0\u6CD5\u7533\u8BF7
yami.not.refunds.requested=\u6CA1\u6709\u67E5\u8BE2\u5230\u652F\u4ED8\u8BB0\u5F55\uFF0C\u65E0\u6CD5\u7533\u8BF7\u9000\u6B3E
yami.refund.progress=\u8BA2\u5355\u6B63\u5728\u8FDB\u884C\u9000\u6B3E\u7ED3\u7B97\uFF0C\u8BF7\u52FF\u91CD\u590D\u64CD\u4F5C
yami.unable.refund.information=\u65E0\u6CD5\u83B7\u53D6\u9000\u6B3E\u8BA2\u5355\u4FE1\u606F
yami.refund.amount.check=\u8BE5\u8BA2\u5355\u90E8\u5206\u8BA2\u5355\u9879\u652F\u4ED8\u91D1\u989D\u548C\u79EF\u5206\u4E3A0\uFF0C\u65E0\u6CD5\u4F7F\u7528\u90E8\u5206\u9000\u6B3E\uFF01
yami.refund.platform.amount.check=\u8BE5\u8BA2\u5355\u6709\u4F7F\u7528\u5E73\u53F0\u4F18\u60E0\uFF0C\u65E0\u6CD5\u4F7F\u7528\u90E8\u5206\u9000\u6B3E\uFF01
yami.refund.num.check=\u9000\u6B3E\u7269\u54C1\u6570\u91CF\u5DF2\u8D85\u51FA\u8BA2\u5355\u4E2D\u7684\u6570\u91CF\uFF0C\u4E0D\u5141\u8BB8\u7533\u8BF7
yami.order.processed=\u9000\u6B3E\u8BA2\u5355\u9879\u5DF2\u5904\u7406\uFF0C\u8BF7\u52FF\u91CD\u590D\u7533\u8BF7
yami.order.unfinished.cannot.destroy.account=\u60A8\u7684\u8D26\u6237\u5F53\u524D\u5B58\u5728\u672A\u5B8C\u6210\u7684\u8BA2\u5355\uFF0C\u8BF7\u5F85\u6240\u6709\u8BA2\u5355\u5B8C\u6210\u540E\u518D\u6CE8\u9500\u8D26\u6237
yami.cannot.find=\u67E5\u8BE2\u4E0D\u5230\u9000\u6B3E\u4FE1\u606F
yami.not.permission=\u7533\u8BF7\u5931\u8D25\uFF0C\u60A8\u6CA1\u6709\u8BE5\u6743\u9650
yami.not.submission=\u5F53\u524D\u7533\u8BF7\u7C7B\u578B\u4E0D\u5141\u8BB8\u63D0\u4EA4\u7269\u6D41\u4FE1\u606F\u64CD\u4F5C
yami.not.submission.delivery=\u5F53\u524D\u72B6\u6001\u4E0D\u5141\u8BB8\u63D0\u4EA4\u7269\u6D41\u4FE1\u606F\u64CD\u4F5C
yami.not.update.delivery=\u5F53\u524D\u72B6\u6001\u4E0D\u5141\u8BB8\u66F4\u65B0\u7269\u6D41\u4FE1\u606F\u64CD\u4F5C
yami.revocation.failed=\u64A4\u9500\u5931\u8D25\uFF0C\u9000\u6B3E\u8BA2\u5355\u4E0D\u5B58\u5728
yami.shop.processing.check=\u5356\u5BB6\u6B63\u5728\u5904\u7406\u9000\u6B3E\uFF0C\u4E0D\u80FD\u64A4\u9500\u9000\u6B3E\u7533\u8BF7
yami.user.delivery.check=\u4E70\u5BB6\u5DF2\u53D1\u8D27\uFF0C\u4E0D\u80FD\u64A4\u9500\u9000\u6B3E\u7533\u8BF7
yami.user.receipt.check=\u5356\u5BB6\u5DF2\u6536\u8D27\uFF0C\u4E0D\u80FD\u64A4\u9500\u9000\u6B3E\u7533\u8BF7
yami.refund.success.check=\u9000\u6B3E\u6210\u529F\uFF0C\u4E0D\u80FD\u64A4\u9500\u9000\u6B3E\u7533\u8BF7
yami.refund.finish.check=\u8BE5\u8BA2\u5355\u6240\u6709\u5546\u54C1\u90FD\u8FDB\u884C\u9000\u6B3E\uFF0C\u5DF2\u65E0\u6CD5\u53D6\u6D88\u9000\u6B3E
yami.refund.status.check=\u64A4\u9500\u5931\u8D25\uFF0C\u5F53\u524D\u72B6\u6001\u4E0D\u5141\u8BB8\u6B64\u64CD\u4F5C
yami.failed.not.exist=\u67E5\u770B\u5931\u8D25\uFF0C\u8BE5\u9000\u6B3E\u8BA2\u5355\u4E0D\u5B58\u5728
yami.failed.not.permiso=\u67E5\u770B\u5931\u8D25\uFF0C\u60A8\u6CA1\u6709\u6B64\u6743\u9650
yami.item.not.exist=\u8BE5\u7269\u54C1\u5728\u8BA2\u5355\u4E2D\u4E0D\u5B58\u5728
yami.shopCart.take.off=\u5DF2\u4E0B\u67B6
yami.contains.unrecognized.items=\u8D2D\u7269\u8F66\u5305\u542B\u65E0\u6CD5\u8BC6\u522B\u7684\u5546\u54C1
yami.no.auth.update.form=\u60A8\u6CA1\u6709\u6743\u9650\u66F4\u6539\u8BE5\u62A5\u8868\u7684\u6570\u636E
yami.auth.fail=\u6388\u6743\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u6388\u6743
yami.img.name.exist=\u56FE\u7247\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
yami.area.delete=\u8BF7\u5148\u5220\u9664\u5B50\u5730\u533A
yami.delivery.using=\u6B63\u5728\u4F7F\u7528\u4E2D\uFF0C\u65E0\u6CD5\u8FDB\u884C\u5220\u9664\u64CD\u4F5C
yami.selCity=\u8BF7\u9009\u62E9\u6307\u5B9A\u5305\u90AE\u57CE\u5E02
yami.model=\u6A21\u677F
yami.img.lose=\u56FE\u7247\u4E22\u5931\uFF0C\u8BF7\u91CD\u65B0\u4E0A\u4F20\u56FE\u7247
yami.unable.get.classification=\u65E0\u6CD5\u83B7\u53D6\u5206\u7C7B\u4FE1\u606F
yami.select.notify.check=\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u79CD\u901A\u77E5\u65B9\u5F0F
yami.select.notify.type.check=\u5DF2\u7ECF\u5B58\u5728\u5F53\u524D\u6D88\u606F\u7C7B\u578B\u7684\u5176\u4ED6\u914D\u7F6E\uFF0C\u8BF7\u53BB\u8FDB\u884C\u4FEE\u6539\u64CD\u4F5C\u3002
yami.flush.category.tips=\u8BF7\u5148\u524D\u5F80 \u3010\u4F1A\u5458\u7BA1\u7406\u3011-> \u3010\u79EF\u5206\u6210\u957F\u503C\u914D\u7F6E\u3011-> \u3010\u79EF\u5206\u83B7\u53D6\u914D\u7F6E\u3011 \u8FDB\u884C\u914D\u7F6E\u5E76\u4FDD\u5B58
yami.form.time.check=\u8BF7\u9009\u62E9\u8D77\u6B62\u65F6\u95F4
yami.form.data.error=\u8BE5\u62A5\u8868\u6570\u636E\u6709\u8BEF\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u65B0\u8F93\u5165
yami.coupon.no.auth=\u6CA1\u6709\u6743\u9650\u4FEE\u6539\u8BE5\u4F18\u60E0\u5238\u4FE1\u606F
yami.coupon.receive.finish=\u8BE5\u5238\u65E0\u6CD5\u88AB\u9886\u53D6\u6216\u8005\u8BE5\u5238\u9886\u5B8C\u4E86!
yami.coupon.stock.enough=\u4F18\u60E0\u5238\u5E93\u5B58\u4E0D\u8DB3
yami.coupon.user.limit=\u4F18\u60E0\u5238\u6570\u91CF\u8D85\u51FA\u9886\u53D6\u4E0A\u9650
yami.coupon.limit.check=\u4F18\u60E0\u5238\u9650\u9886\u6570\u91CF\u9700\u5927\u4E8E0
yami.coupon.time.check=\u5F00\u59CB\u65F6\u95F4\u9700\u5927\u4E8E\u7ED3\u675F\u65F6\u95F4
yami.coupon.launch.time.check = \u4F18\u60E0\u5238\u6295\u653E\u65F6\u95F4\u4E0D\u80FD\u4E3A\u7A7A
yami.coupon.launch.time.check1 = \u6295\u653E\u65F6\u95F4\u9700\u5927\u4E8E\u5F53\u524D\u65F6\u95F4
yami.coupon.launch.time.lt.endtime = \u6295\u653E\u65F6\u95F4\u8981\u5C0F\u4E8E\u5931\u6548\u65F6\u95F4
yami.coupon.no.exist=\u4F18\u60E0\u5238\u4E0D\u5B58\u5728
yami.coupon.delete.check1=\u8BE5\u4F18\u60E0\u5238\u5DF2\u88AB\u9886\u53D6\uFF0C\u5220\u9664\u5931\u8D25
yami.coupon.delete.check2=\u8BE5\u4F18\u60E0\u5238\u5DF2\u6295\u653E\uFF0C\u5220\u9664\u5931\u8D25
yami.coupon.receive.success=\u9886\u53D6\u4F18\u60E0\u5238\u6210\u529F
yami.live.time.check=\u5F00\u59CB\u65F6\u95F4\u4E0D\u80FD\u5927\u4E8E\u7ED3\u675F\u65F6\u95F4
yami.live.time.one.check=\u5F00\u59CB\u65F6\u95F4\u9700\u8981\u5728\u5F53\u524D\u65F6\u95F4\u768415\u5206\u949F\u540E,\u5E76\u4E14\u4E0D\u80FD\u57286\u4E2A\u6708\u540E!
yami.live.time.two.check=\u5F00\u59CB\u65F6\u95F4\u548C\u7ED3\u675F\u65F6\u95F4\u95F4\u9694\u4E0D\u5F97\u77ED\u4E8E30\u5206\u949F\uFF0C\u4E0D\u5F97\u8D85\u8FC724\u5C0F\u65F6\uFF01
yami.live.name.check=\u540D\u79F0\u957F\u5EA6\u4E0D\u7B26\u5408\u89C4\u5219\uFF01
yami.live.user.name.check=\u4E3B\u64AD\u5FAE\u4FE1\u53F7\u672A\u7ECF\u8FC7\u3010\u5C0F\u7A0B\u5E8F\u76F4\u64AD\u3011\u5C0F\u7A0B\u5E8F\u5B9E\u540D\u8BA4\u8BC1\uFF01
yami.live.room.check1=\u672A\u5728\u5C0F\u7A0B\u5E8F\u7BA1\u7406\u540E\u53F0\u914D\u7F6E\u5BA2\u670D
yami.live.config.check=\u521B\u5EFA\u5931\u8D25\uFF0C\u8BF7\u4ED4\u7EC6\u68C0\u67E5\u76F4\u64AD\u95F4\u7684\u914D\u7F6E\uFF01
yami.live.room.delete.fail = \u5220\u9664\u76F4\u64AD\u95F4\u5931\u8D25
yami.live.platform.numLimit=\u5E73\u53F0\u4ECA\u65E5\u53EF\u7528\u83B7\u53D6\u76F4\u64AD\u95F4\u4FE1\u606F\u7684\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650\uFF01
yami.live.prod.name.check=\u540D\u79F0\u957F\u5EA6\u975E\u6CD5,\u6700\u5C113\u4E2A\u6C49\u5B57\u6216\u80056\u4E2A\u5B57\u7B26\u3001\u6700\u592714\u4E2A\u6C49\u5B57\uFF01
yami.live.room.name.check=\u76F4\u64AD\u95F4\u540D\u79F0\u957F\u5EA6\u975E\u6CD5,\u6700\u77ED3\u4E2A\u6C49\u5B57\uFF0C\u6700\u957F17\u4E2A\u6C49\u5B57\uFF01
yami.live.room.name.check2=\u4E3B\u64AD\u6635\u79F0\u957F\u5EA6\u975E\u6CD5\uFF0C\u6700\u77ED2\u4E2A\u6C49\u5B57\uFF0C\u6700\u957F15\u4E2A\u6C49\u5B57
yami.live.room.top.check=\u7F6E\u9876\u5DF2\u8FBE\u4E0A\u965010\u4E2A\u65E0\u6CD5\u8FDB\u884C\u7F6E\u9876\uFF0C\u8BF7\u5148\u53D6\u6D88\u5176\u4F59\u76F4\u64AD\u95F4\u7684\u7F6E\u9876
yami.live.prod.delete.fail=\u5220\u9664\u76F4\u64AD\u5546\u54C1\u5931\u8D25
yami.live.prod.update.fail=\u66F4\u65B0\u76F4\u64AD\u5546\u54C1\u5E93\u5931\u8D25
yami.live.prod.not.exist=\u5F53\u524D\u76F4\u64AD\u5546\u54C1\u5173\u8054\u7684\u5546\u54C1\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5220\u9664
yami.live.prod.examine=\u5546\u54C1\u6B63\u5728\u5BA1\u6838\u4E2D\uFF0C\u65E0\u6CD5\u8FDB\u884C\u4FEE\u6539
yami.prod.pre.sell=\u9884\u552E\u5546\u54C1\u4E0D\u80FD\u52A0\u5165\u8D2D\u7269\u8F66\uFF01
yami.live.img.isWebp=\u56FE\u7247\u4E0D\u80FD\u4F7F\u7528webp\u683C\u5F0F,\u63A8\u8350\u4F7F\u7528jpg\u6216png
yami.order=\u8BA2\u5355
yami.order.station.check=\u9000\u6B3E\u4E2D\uFF0C\u65E0\u6CD5\u81EA\u63D0
yami.order.station.finish=\u5DF2\u63D0\u8D27
yami.prod.no.join.activity=\u5F53\u524D\u5546\u54C1\u6CA1\u6709\u53C2\u52A0\u8BE5\u62FC\u56E2\u6D3B\u52A8
yami.activity.no.start=\u5F53\u524D\u62FC\u56E2\u6D3B\u52A8\u672A\u5F00\u59CB
yami.activity.already.end=\u5F53\u524D\u62FC\u56E2\u6D3B\u52A8\u5DF2\u7ED3\u675F
yami.activity.already.invalid=\u5F53\u524D\u62FC\u56E2\u6D3B\u52A8\u5DF2\u5931\u6548
yami.job.get.error=\u83B7\u53D6\u5B9A\u65F6\u4EFB\u52A1CronTrigger\u51FA\u73B0\u5F02\u5E38
yami.prod.category.error=\u8BF7\u9009\u62E9\u5E73\u53F0\u7684\u4E09\u7EA7\u5206\u7C7B
yami.user.payType.error=\u8BF7\u4F7F\u7528\u5FAE\u4FE1\u6216\u652F\u4ED8\u5B9D\u8FDB\u884C\u652F\u4ED8
yami.notify.tag.msg=\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u4E2A\u6807\u7B7E\uFF01
yami.information.is.wrong=\u60A8\u7684\u4FE1\u606F\u6709\u8BEF\uFF0C\u8BF7\u5C1D\u8BD5\u5237\u65B0\u540E\u518D\u8FDB\u884C\u64CD\u4F5C
yami.balance.is.insufficient=\u60A8\u7684\u4F59\u989D\u4E0D\u8DB3\uFF0C\u8BF7\u5148\u5145\u503C\u4F59\u989D
yami.id.number.already.exists=\u8BE5\u8EAB\u4EFD\u8BC1\u53F7\u7801\u5DF2\u5B58\u5728
yami.phone.number.already.exists=\u8BE5\u624B\u673A\u53F7\u7801\u5DF2\u5728\u7CFB\u7EDF\u5B58\u5728
yami.phone.number.not.exists=\u8BE5\u8D26\u53F7\u4E0D\u5B58\u5728
yami.get.user.cash.info=\u65E0\u6CD5\u83B7\u53D6\u63D0\u73B0\u4FE1\u606F
yami.get.user.withdraw.info=\u65E0\u6CD5\u83B7\u53D6\u7528\u6237\u94B1\u5305\u4FE1\u606F
yami.withdrawCash.update.no.auth=\u6CA1\u6709\u6743\u9650\u4FEE\u6539\u63D0\u73B0\u4FE1\u606F
yami.user.tag.not.exists=\u7528\u6237\u6807\u7B7E\u4E0D\u5B58\u5728
yami.user.tag.type.not.right=\u6807\u7B7E\u7C7B\u578B\u4E0D\u5BF9\u52B2
yami.user.tag.refresh.limit=\u5237\u65B0\u95F4\u9694\u4E0D\u80FD\u5C0F\u4E8E\u4E00\u5206\u949F
yami.user.tag.time=\u5F00\u59CB\u65F6\u95F4\u4E0D\u80FD\u6BD4\u7ED3\u675F\u65F6\u95F4\u665A
yami.user.tag.number=\u6700\u5C0F\u6B21\u6570\u4E0D\u80FD\u6BD4\u6700\u5927\u6B21\u6570\u5927
yami.user.tag.amount=\u6700\u5C0F\u91D1\u989D\u4E0D\u80FD\u6BD4\u6700\u5927\u91D1\u989D\u5927
yami.finance.transactionTime=\u4EA4\u6613\u65F6\u95F4
yami.finance.orderNumber=\u8BA2\u5355\u7F16\u53F7
yami.finance.incOrPay=\u6536\u652F\u7C7B\u578B
yami.finance.payType=\u652F\u4ED8\u65B9\u5F0F
yami.finance.transactionAmount=\u4EA4\u6613\u91D1\u989D
yami.finance.reportTitle=\u8D22\u52A1\u660E\u7EC6\u62A5\u8868
yami.finance.income=\u6536\u5165
yami.finance.pay=\u652F\u51FA
yami.payType.pay0=\u79EF\u5206\u652F\u4ED8
yami.payType.pay1=\u5FAE\u4FE1\u652F\u4ED8
yami.payType.pay2=\u652F\u4ED8\u5B9D\u652F\u4ED8
yami.payType.pay3=\u5FAE\u4FE1\u626B\u7801\u652F\u4ED8
yami.payType.pay4=\u5FAE\u4FE1H5\u652F\u4ED8
yami.payType.pay5=\u5FAE\u4FE1\u516C\u4F17\u53F7
yami.payType.pay6=\u652F\u4ED8\u5B9DH5\u652F\u4ED8
yami.payType.pay7=\u652F\u4ED8\u5B9DAPP\u652F\u4ED8
yami.payType.pay8=\u5FAE\u4FE1APP\u652F\u4ED8
yami.payType.pay9=\u7528\u6237\u4F59\u989D\u652F\u4ED8
yami.store.name.no.exist=\u5E97\u94FA\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
yami.store.brief.check=\u5E97\u94FA\u7B80\u4ECB\u957F\u5EA6\u5E94\u8BE5\u5C0F\u4E8E{max}
yami.store.name.check1=\u5546\u54C1\u540D\u79F0\u957F\u5EA6\u5E94\u8BE5\u5C0F\u4E8E{max}
yami.store.phone.no.exist=\u5E97\u94FA\u8054\u7CFB\u7535\u8BDD\u4E0D\u80FD\u4E3A\u7A7A
yami.tag.num.check=\u6761\u4EF6\u6807\u7B7E\u6570\u91CF\u8D85\u8FC7\u4E0A\u9650
yami.tag.shop.check=\u60A8\u65E0\u6743\u5BF9\u6B64\u5546\u54C1\u6807\u7B7E\u8FDB\u884C\u64CD\u4F5C
yami.tag.prod.check=\u8BF7\u9009\u62E9\u9700\u8981\u52A0\u5165\u5206\u7EC4\u7684\u5546\u54C1
yami.tag.prod.delete.check=\u8BF7\u9009\u62E9\u9700\u8981\u5220\u9664\u7684\u5206\u7EC4\u4E2D\u5546\u54C1
yami.tag.prod.update.check=\u8BF7\u9009\u62E9\u9700\u8981\u4FEE\u6539\u7684\u5206\u7EC4\u4E2D\u5546\u54C1
yami.live.user.check=\u5FAE\u4FE1\u53F7\u4E0D\u5408\u89C4
yami.live.user.check1=\u5FAE\u4FE1\u53F7\u9700\u8981\u5B9E\u540D\u8BA4\u8BC1\uFF0C\u4EC5\u8BBE\u7F6E\u4E3B\u64AD\u89D2\u8272\u65F6\u53EF\u80FD\u51FA\u73B0
yami.live.user.check2=\u91CD\u590D\u6DFB\u52A0\u89D2\u8272
yami.live.user.check3=\u6DFB\u52A0\u89D2\u8272\u8FBE\u5230\u4E0A\u9650
yami.live.user.check4=\u4E3B\u64AD\u89D2\u8272\u5220\u9664\u5931\u8D25\uFF0C\u8BE5\u4E3B\u64AD\u5B58\u5728\u672A\u5F00\u64AD\u7684\u76F4\u64AD\u95F4
yami.live.user.super.admin=\u8D85\u7EA7\u7BA1\u7406\u5458\uFF0C
yami.live.user.admin=\u7BA1\u7406\u5458\uFF0C
yami.live.user.anchor=\u4E3B\u64AD\uFF0C
yami.live.user.operators=\u8FD0\u8425\u8005\uFF0C
yami.live.user.check5=\u7528\u6237\u5DF2\u5177\u6709\u7BA1\u7406\u5458\u89D2\u8272
yami.live.user.check6=\u4E3B\u64AD\u89D2\u8272\u5220\u9664\u5931\u8D25\uFF0C\u8BE5\u4E3B\u64AD\u4E0D\u5B58\u5728\u6216\u8005\u5B58\u5728\u672A\u5F00\u64AD\u7684\u76F4\u64AD\u95F4
yami.tag.name.exist=\u6807\u7B7E\u540D\u79F0\u5DF2\u5B58\u5728
yami.customer.no.online=\u9009\u62E9\u8F6C\u53D1\u7684\u5BA2\u670D\u6216\u7528\u6237\u5DF2\u4E0D\u5728\u7EBF\u4E0A\uFF0C\u65E0\u6CD5\u8FDB\u884C\u8F6C\u53D1!
yami.user.balance.check=\u7528\u6237\u5F53\u524D\u4F59\u989D\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u51CF\u5C11
yami.excel.user.info=\u7528\u6237\u4FE1\u606F\u8868
yami.excel.user.number=\u5E8F\u53F7
yami.excel.user.userNickname=\u7528\u6237\u6635\u79F0
yami.excel.user.userName=\u7528\u6237\u540D\u79F0
yami.excel.user.contactNumber=\u8054\u7CFB\u7535\u8BDD
yami.excel.user.memberLevel=\u4F1A\u5458\u7B49\u7EA7
yami.excel.user.memberType=\u4F1A\u5458\u7C7B\u578B
yami.excel.user.accScore=\u7528\u6237\u79EF\u5206
yami.excel.user.status=\u72B6\u6001
yami.excel.user.amountConsum=\u6D88\u8D39\u91D1\u989D
yami.excel.user.amountActPaid=\u5B9E\u4ED8\u91D1\u989D
yami.excel.user.numberConsum=\u6D88\u8D39\u6B21\u6570
yami.excel.user.aveDiscount=\u5E73\u5747\u6298\u6263
yami.excel.user.rechargeAmount=\u5145\u503C\u91D1\u989D
yami.excel.user.topUpTimes=\u5145\u503C\u6B21\u6570
yami.excel.user.refundAmount=\u9000\u6B3E\u91D1\u989D
yami.excel.user.numberOfRefund=\u9000\u6B3E\u6B21\u6570
yami.excel.user.accPoints=\u7D2F\u8BA1\u79EF\u5206
yami.excel.user.currBalance=\u5F53\u524D\u4F59\u989D
yami.excel.user.accBalance=\u7D2F\u8BA1\u4F59\u989D
yami.excel.user.regTime=\u6CE8\u518C\u65F6\u95F4
yami.excel.user.receConsumDate=\u6700\u8FD1\u6D88\u8D39\u65F6\u95F4
yami.web.config.check=\u8BF7\u81F3\u5C11\u5F00\u542F\u4E00\u4E2A\u914D\u7F6E\u540E\u518D\u5173\u95ED\u5F53\u524D\u914D\u7F6E
yami.average.retention.rate=\u5E73\u5747\u7559\u5B58\u7387
yami.prod.set.top.check=\u53EA\u80FD\u7F6E\u9876\u5DF2\u4E0A\u67B6\u7684\u5546\u54C1
yami.login.password.check=\u534A\u5C0F\u65F6\u5185\u8F93\u5165\u5BC6\u7801\u9519\u8BEF\u5341\u6B21\uFF0C\u5DF2\u9650\u5236\u767B\u5F5530\u5206\u949F
yami.product.sku.invalid=\u5E93\u5B58\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u5237\u65B0\u9875\u9762
yami.group.name.duplicate=\u5206\u7EC4\u540D\u5DF2\u5B58\u5728
yami.invoice.shopId.notNull=\u5E97\u94FAid\u4E0D\u80FD\u4E3A\u7A7A
yami.invoice.invoiceId.duplicate=\u8BE5\u8BA2\u5355\u5DF2\u7ECF\u7533\u8BF7\u53D1\u7968\uFF0C\u8BF7\u52FF\u91CD\u590D\u7533\u8BF7\uFF01
yami.invoice.not.user=\u65E0\u6CD5\u67E5\u770B\u975E\u5F53\u524D\u7528\u6237\u7684\u53D1\u7968\u4FE1\u606F
yami.file.isNot.exist=\u8BF7\u4E0A\u4F20\u6587\u4EF6
yami.file.isNot.shop=\u65E0\u6CD5\u67E5\u770B\u975E\u672C\u5E97\u94FA\u7684\u6587\u4EF6
yami.prod.common.invalid=\u6570\u636E\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u5237\u65B0\u9875\u9762
yami.prod.name.not.blank=\u4EA7\u54C1\u4E2D\u6587\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
yami.prod.brief.not.blank=\u4EA7\u54C1\u4E2D\u6587\u5356\u70B9\u4E0D\u80FD\u4E3A\u7A7A
yami.prod.category.not.blank=\u4EA7\u54C1\u5206\u7C7B\u4E0D\u80FD\u4E3A\u7A7A
yami.platform.category.not.blank=\u5E73\u53F0\u5206\u7C7B\u4E0D\u80FD\u4E3A\u7A7A
yami.prod.shop.type.not.blank=\u4EA7\u54C1\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
yami.prod.shop.category.not.blank=\u4EA7\u54C1\u5E97\u94FA\u5206\u7C7B\u4E0D\u80FD\u4E3A\u7A7A
yami.prod.dvy.type.not.blank=\u4EA7\u54C1\u914D\u9001\u65B9\u5F0F\u4E0D\u80FD\u4E3A\u7A7A
yami.prod.transport.not.exist=\u4EA7\u54C1\u8FD0\u8D39\u6A21\u677F\u4E0D\u5B58\u5728
yami.prod.pic.limit = \u4E0A\u4F20\u56FE\u7247\u6570\u91CF\u8D85\u8FC7\u9650\u5236
yami.prod.pic.format.error = \u4E0A\u4F20\u56FE\u7247\u683C\u5F0F\u9519\u8BEF
yami.prod.video.format.error = \u4E0A\u4F20\u89C6\u9891\u683C\u5F0F\u9519\u8BEF
yami.prod.video.too.large.error = \u4E0A\u4F20\u89C6\u9891\u8FC7\u5927
yami.product.not.shelf=\u8BE5\u5546\u54C1\u672A\u4E0A\u67B6\uFF0C\u8BF7\u9009\u62E9\u522B\u7684\u5546\u54C1
yami.supplier.name.not.blank=\u4F9B\u5E94\u5546\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
yami.supplier.not.null=\u4F9B\u5E94\u5546\u4E0D\u80FD\u4E3A\u7A7A
yami.supplier.category.not.exit=\u4F9B\u5E94\u5546\u5206\u7C7B\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u7981\u7528
yami.supplier.category.already.exit=\u4F9B\u5E94\u5546\u5206\u7C7B\u5DF2\u5B58\u5728
yami.supplier.supplierName.exist=\u4F9B\u5E94\u5546\u540D\u79F0\u5DF2\u5B58\u5728
yami.supplier.supplierName.than=\u4F9B\u5E94\u5546\u540D\u79F0\u5B57\u6570\u4E0D\u80FD\u8D85\u8FC750
yami.supplier.contactName.than=\u8054\u7CFB\u4EBA\u540D\u79F0\u4E0D\u80FD\u8D85\u8FC750
yami.supplier.tel.error=\u5355\u4F4D\u7535\u8BDD\u683C\u5F0F\u9519\u8BEF
yami.supplier.contactTel.error=\u8054\u7CFB\u7535\u8BDD\u683C\u5F0F\u9519\u8BEF
yami.supplier.mail.error=\u90AE\u7BB1\u683C\u5F0F\u9519\u8BEF
yami.supplier.qqNumber.error=qq\u53F7\u683C\u5F0F\u9519\u8BEF
yami.supplier.wxNumber.error=\u5FAE\u4FE1\u53F7\u683C\u5F0F\u9519\u8BEF
yami.supplier.prod.not.shop=\u65E0\u6CD5\u67E5\u770B\u975E\u672C\u5E97\u94FA\u7684\u5546\u54C1
yami.sku.party.code.exist=\u5546\u54C1\u7F16\u7801\u5DF2\u5B58\u5728
yami.sku.party.code.not.exist=\u5546\u54C1\u7F16\u7801\u4E0D\u5B58\u5728\u6216\u8BE5\u5546\u54C1\u5DF2\u88AB\u5220\u9664
yami.sku.party.code.is.repeated=\u8BE5\u5546\u54C1\u7F16\u7801\u4E0B\u5B58\u5728\u591A\u4E2A\u5546\u54C1\u89C4\u683C\uFF0C\u8BF7\u66F4\u65B0\u5BF9\u5E94\u7684\u5546\u54C1\u89C4\u683C\u7F16\u7801\u540E\u91CD\u65B0\u5BFC\u5165
yami.station.no.exist=\u81EA\u63D0\u70B9\u4FE1\u606F\u4E0D\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u81EA\u63D0\u70B9
yami.order.not.null=\u8BA2\u5355\u6240\u9700\u5FC5\u586B\u9879\u4E0D\u80FD\u4E3A\u7A7A\uFF01
yami.order.coupon.not.start=\u5361\u5238\u672A\u5230\u4F7F\u7528\u65F6\u95F4\u6216\u5DF2\u8FC7\u671F\uFF01
yami.order.coupon.expired=\u5361\u5238\u5DF2\u8FC7\u671F\uFF01
yami.order.coupon.exist=\u5361\u5238\u4E0D\u5B58\u5728\u6216\u8005\u5DF2\u6838\u9500\uFF01
yami.order.virtual.check=\u9000\u6B3E\u4E2D\uFF0C\u65E0\u6CD5\u6838\u9500\uFF01
yami.order.virtual.check2=\u5F53\u524D\u865A\u62DF\u5546\u54C1\u8BA2\u5355\u65E0\u9700\u6838\u9500
yami.virtual.prod.check=\u865A\u62DF\u5546\u54C1\u4E0D\u80FD\u52A0\u5165\u8D2D\u7269\u8F66
yami.order.virtual.refund.check1=\u5F53\u524D\u8BA2\u5355\u4E0D\u80FD\u9000\u6B3E\uFF0C\u8BF7\u8054\u7CFB\u5BA2\u670D
yami.order.virtual.refund.check2=\u865A\u62DF\u5546\u54C1\u8BA2\u5355\u4E0D\u80FD\u9000\u8D27\u9000\u6B3E
yami.order.virtual.refund.check3=\u5F53\u524D\u8BA2\u5355\u6838\u9500\u65F6\u95F4\u5DF2\u8FC7\u671F\u4E0D\u80FD\u7533\u8BF7\u9000\u6B3E\uFF0C\u8BF7\u8054\u7CFB\u5BA2\u670D
yami.order.virtual.refund.check4=\u5F53\u524D\u8BA2\u5355\u5DF2\u7ECF\u5168\u90E8\u6838\u9500\u5B8C\u6210\u4E0D\u80FD\u7533\u8BF7\u9000\u6B3E\uFF0C\u8BF7\u8054\u7CFB\u5BA2\u670D
yami.order.virtual.refund.check5=\u5F53\u524D\u8BA2\u5355\u53EF\u4EE5\u9000\u6B3E\u7684\u6570\u91CF\u8D85\u51FA
yami.order.prod.type.check=\u5546\u54C1\u521B\u5EFA\u540E\u4E0D\u80FD\u4FEE\u6539\u5546\u54C1\u7C7B\u578B
yami.prod.type.check=\u5546\u54C1\u7C7B\u578B\u6539\u53D8\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u540E\u91CD\u8BD5
yami.take.stock.time.not.null=\u76D8\u70B9\u5F00\u59CB\u65F6\u95F4\u4E0D\u80FD\u4E3A\u7A7A
yami.take.stock.prod.null=\u76D8\u70B9\u5546\u54C1\u4E0D\u80FD\u4E3A\u7A7A
yami.take.stock.id.not.null=\u76D8\u70B9Id\u4E0D\u80FD\u4E3A\u7A7A
yami.take.stock.message.error=\u5F53\u524D\u76D8\u70B9\u4FE1\u606F\u4E0D\u5C5E\u4E8E\u4F60\u7684\u5E97\u94FA
yami.take.stock.status.error=\u5F53\u524D\u76D8\u70B9\u4EFB\u52A1\u5DF2\u5B8C\u6210\u6216\u5DF2\u4F5C\u5E9F\uFF0C\u8BF7\u8FD4\u56DE\u5217\u8868\u9875\u9762\u540E\u5237\u65B0
yami.take.stock.import.error=\u8BE5\u76D8\u70B9\u5355\u5DF2\u6709\u5546\u54C1\u5BFC\u5165\uFF0C\u65E0\u6CD5\u4F7F\u7528\u6279\u91CF\u5BFC\u5165\u529F\u80FD
yami.take.stock.count.not.null=\u76D8\u70B9\u6570\u91CF\u4E0D\u80FD\u4E3A\u7A7A
yami.shop.sku.is.null=\u5546\u54C1\u89C4\u683C\u4E0D\u5B58\u5728
yami.shop.stock.update.error=\u5E93\u5B58\u66F4\u65B0\u5931\u8D25
yami.shop.total.stock.not.null=\u5546\u54C1\u5B9E\u76D8\u5E93\u5B58\u4E0D\u80FD\u4E3A\u7A7A
yami.purchases.order.voided=\u6B64\u8BA2\u5355\u5DF2\u4F5C\u5E9F
yami.purchases.order.complete=\u6B64\u8BA2\u5355\u5DF2\u5B8C\u6210
yami.purchases.order.party.code=\u5546\u54C1\u7F16\u7801\u4E0D\u80FD\u4E3A\u7A7A
yami.purchases.order.stock.num=\u91C7\u8D2D\u6570\u91CF\u4E0D\u80FD\u4E3A\u7A7A
yami.purchases.order.error.code=\u9519\u8BEF\u7684\u5546\u54C1\u7F16\u53F7
yami.supplier.status.error=\u8BE5\u4F9B\u5E94\u5546\u5DF2\u88AB\u7981\u7528\uFF0C\u8BF7\u542F\u7528\u540E\u518D\u64CD\u4F5C
yami.sku.party.code=\u5546\u54C1\u7F16\u7801
yami.is.exist=\u5DF2\u5B58\u5728
yami.properties=\u9500\u552E\u5C5E\u6027\u7EC4\u5408\u5B57\u7B26\u4E32
yami.properties.error=\u683C\u5F0F\u9519\u8BEF
yami.sku.name=\u89C4\u683C\u540D
yami.is.duplicate=\u91CD\u590D
yami.sys.access.key.id.not.null=sysAccessKeyId \u4E0D\u80FD\u4E3A\u7A7A
yami.supplier.not.exist.or.disabled=\u4F9B\u5E94\u5546\u4E0D\u5B58\u5728\u6216\u5DF2\u7981\u7528
yami.purchased.order.not.exist=\u91C7\u8D2D\u8BA2\u5355\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5\uFF01
yami.purchased.prod.not.exist.or.disabled=\u91C7\u8D2D\u5546\u54C1\u4E0D\u5B58\u5728\u6216\u5DF2\u5220\u9664\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5\uFF01
yami.data.deleted.or.not.exist=\u6570\u636E\u5DF2\u5220\u9664\u6216\u4E0D\u5B58\u5728
yami.platform.prod.offline.check=\u5F53\u524D\u5546\u54C1/\u6D3B\u52A8\u5DF2\u8FDD\u89C4\u4E0B\u67B6\u6216\u8005\u6B63\u5728\u5BA1\u6838\u4E2D\uFF0C\u4E0D\u80FD\u8FDB\u884C\u4E0B\u67B6\u64CD\u4F5C
yami.order.coupon.expire.check=\u5F53\u524D\u9009\u62E9\u7684\u4F18\u60E0\u5238\u5DF2\u7ECF\u8FC7\u671F\uFF0C\u8BF7\u8FD4\u56DE\u91CD\u65B0\u63D0\u4EA4\u8BA2\u5355
yami.order.discount.expire.check=\u5F53\u524D\u9009\u62E9\u7684\u6EE1\u51CF\u6D3B\u52A8\u5DF2\u7ECF\u8FC7\u671F\uFF0C\u8BF7\u8FD4\u56DE\u91CD\u65B0\u63D0\u4EA4\u8BA2\u5355
yami.order.combo.expire.check=\u5F53\u524D\u9009\u62E9\u7684\u5957\u9910\u6D3B\u52A8\u5DF2\u7ECF\u8FC7\u671F\uFF0C\u8BF7\u8FD4\u56DE\u91CD\u65B0\u63D0\u4EA4\u8BA2\u5355
yami.order.giveaway.expire.check=\u5F53\u524D\u9009\u62E9\u7684\u8D60\u54C1\u6D3B\u52A8\u5DF2\u7ECF\u8FC7\u671F\uFF0C\u8BF7\u8FD4\u56DE\u91CD\u65B0\u63D0\u4EA4\u8BA2\u5355
yami.order.pay.type.check=\u5E73\u53F0\u6682\u4E0D\u652F\u6301\u5F53\u524D\u652F\u4ED8\u65B9\u5F0F\uFF0C\u8BF7\u5237\u65B0\u540E\u5728\u9009\u62E9
yami.platform.delivery.name.repeat=\u7269\u6D41\u540D\u79F0\u4E0D\u80FD\u91CD\u590D
yami.prod.parameter.format.error=\u5546\u54C1\u53C2\u6570\u683C\u5F0F\u6709\u8BEF
yami.balance.than.max.balance=\u60A8\u7684\u4F59\u989D\u52A0\u5145\u503C\u7684\u4F59\u989D\u5C06\u5927\u4E8E\u6700\u5927\u4F59\u989D\uFF0C\u4E0D\u80FD\u8FDB\u884C\u5145\u503C\u64CD\u4F5C
yami.user.blance.not.exist = \u5F53\u524D\u5145\u503C\u9009\u9879\u5DF2\u4E0D\u5B58\u5728\uFF0C\u8BF7\u5237\u65B0\u91CD\u8BD5
yami.prod.status.change=\u5546\u54C1\u72B6\u6001\u5DF2\u6539\u53D8\uFF0C\u8BF7\u5237\u65B0\u9875\u9762
yami.refund.amount.change.check=\u5F53\u524D\u9000\u6B3E\u5355\u72B6\u6001\u4E0D\u80FD\u4FEE\u6539\u9000\u6B3E\u91D1\u989D\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5
yami.refund.amount.change.check2=\u6574\u5355\u9000\u6B3E\u6682\u4E0D\u652F\u6301\u4FEE\u6539\u9000\u6B3E\u91D1\u989D
yami.refund.amount.change.check3=\u4F7F\u7528\u5E73\u53F0\u4F18\u60E0\u7684\u8BA2\u5355\u4E0D\u80FD\u4FEE\u6539\u9000\u6B3E\u91D1\u989D
yami.order.delivery.num.check=\u8BA2\u5355\u53D1\u8D27\u6570\u91CF\u4E0D\u8DB3\uFF0C\u8BF7\u5237\u65B0\u540E\u518D\u8BD5
yami.active.is.delete=\u6D3B\u52A8\u5DF2\u88AB\u5220\u9664\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u91CD\u8BD5
yami.station.no.exists=\u5F53\u524D\u95E8\u5E97\u4E0D\u5B58\u5728\u6216\u8005\u4E0D\u5728\u8425\u4E1A\u72B6\u6001\uFF0C\u8BF7\u91CD\u8BD5
yami.exprot.prod.sku.error=\u68C0\u6D4B\u5230\u5B58\u5728\u8D85\u8FC7100\u7EC4\u89C4\u683C\u7684\u5546\u54C1\uFF0C\u8BF7\u4FEE\u6539\u540E\u91CD\u65B0\u5BFC\u5165
yami.combo.end.time.error=\u6D3B\u52A8\u7ED3\u675F\u65F6\u95F4\u4E0D\u80FD\u5C0F\u4E8E\u5F53\u524D\u65F6\u95F4
yami.combo.main.prod.not.empty=\u5957\u9910\u4E3B\u5546\u54C1\u4E0D\u80FD\u4E3A\u7A7A
yami.combo.matching.prod.count.error=\u642D\u914D\u5546\u54C1\u6570\u91CF\u9519\u8BEF
yami.combo.prod.delete.after.tips=\u5DF2\u88AB\u5220\u9664\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9
yami.combo.prod.matching.price.after.tips=\u7684\u642D\u914D\u4EF7\u683C\u4E0D\u80FD\u8D85\u8FC7\u5546\u54C1\u539F\u4EF7
yami.combo.not.shop=\u5F53\u524D\u5957\u9910\u4E0D\u5C5E\u4E8E\u60A8\u7684\u5E97\u94FA
yami.combo.already.delete=\u5F53\u524D\u5957\u9910\u5DF2\u88AB\u5220\u9664
yami.combo.update.fail=\u5957\u9910\u4FE1\u606F\u66F4\u65B0\u5931\u8D25\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5
yami.combo.matching.required.not.empty=\u8BF7\u81F3\u5C11\u8BBE\u7F6E\u4E00\u4E2A\u5FC5\u9009\u7684\u642D\u914D\u5546\u54C1
yami.combo.open.error.tips=\u5F53\u524D\u5957\u9910\u7684\u7ED3\u675F\u65F6\u95F4\u5C0F\u4E8E\u5F53\u524D\u65F6\u95F4\uFF0C\u5F00\u542F\u5931\u8D25\uFF0C\u8BF7\u5148\u8BBE\u7F6E\u8BE5\u5957\u9910\u7684\u6D3B\u52A8\u65F6\u95F4
yami.combo.least.num.not.empty=\u8D77\u642D\u6570\u91CF\u4E0D\u80FD\u4E3A\u7A7A
yami.combo.not.find.prod=\u627E\u4E0D\u5230\u5546\u54C1\u4FE1\u606F
yami.combo.info.error=\u4FE1\u606F\u9519\u8BEF
yami.combo.delete.fail=\u5220\u9664\u5931\u8D25,\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5
yami.combo.already.invalid=\u5F53\u524D\u5957\u9910\u6D3B\u52A8\u5DF2\u5931\u6548
yami.combo.product.already.delete.rear.tips=\u5DF2\u88AB\u5220\u9664\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9
yami.combo.product.already.disable.rear.tips=\u5DF2\u88AB\u7981\u7528\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9
yami.combo.spec.already=\u7684\u89C4\u683C
yami.giveaway.not.on.shop=\u8BE5\u8D60\u54C1\u4FE1\u606F\u4E0D\u5C5E\u4E8E\u4F60\u7684\u5E97\u94FA
yami.giveaway.prod.error=\u5B58\u5728\u9519\u8BEF\u7684\u5546\u54C1\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u65B0\u9009\u62E9
yami.giveaway.virtual.prod.error=\u5C5E\u4E8E\u865A\u62DF\u5546\u54C1\uFF0C\u4E0D\u80FD\u8BBE\u7F6E\u4E3A\u8D60\u9001\u5546\u54C1
yami.giveaway.activity.time.error.tips1=\u6D3B\u52A8\u65F6\u95F4\u4E0E\u8D60\u54C1\u3010
yami.giveaway.activity.time.error.tips2=\u3011\u7684\u65F6\u95F4\u53D1\u751F\u51B2\u7A81\uFF0C\u4E00\u4E2A\u4E3B\u5546\u54C1\u540C\u4E00\u65F6\u95F4\u4E0D\u80FD\u8BBE\u7F6E\u591A\u4E2A\u8D60\u54C1\u6D3B\u52A8\uFF0C\u3010
yami.giveaway.activity.time.error.tips3=\u3011\u7684\u6D3B\u52A8\u65F6\u95F4\u4E3A
yami.giveaway.activity.time.error.tips4=\u5F53\u524D\u8D60\u54C1\u7684\u7ED3\u675F\u65F6\u95F4\u5C0F\u4E8E\u5F53\u524D\u65F6\u95F4\uFF0C\u5F00\u542F\u5931\u8D25\uFF0C\u8BF7\u5148\u8BBE\u7F6E\u8BE5\u8D60\u54C1\u7684\u6D3B\u52A8\u65F6\u95F4
yami.giveaway.activity.time.error.tips5=\u4E00\u4E2A\u4E3B\u5546\u54C1\u4E0D\u80FD\u8BBE\u7F6E\u591A\u4E2A\u8D60\u54C1\u6D3B\u52A8
yami.giveaway.time.to=\u81F3
yami.giveaway.already.invalid=\u5F53\u524D\u8D60\u54C1\u6D3B\u52A8\u5DF2\u5931\u6548
yami.giveaway.already.delete=\u5F53\u524D\u8D60\u54C1\u5DF2\u88AB\u5220\u9664
yami.giveaway.update.fail=\u8D60\u54C1\u4FE1\u606F\u66F4\u65B0\u5931\u8D25\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5
yami.giveaway.refund.price.error=\u8D60\u54C1\u7684\u603B\u552E\u540E\u4EF7\u4E0D\u80FD\u8D85\u8FC7\u4E3B\u5546\u54C1\u4EF7\u683C
yami.prod.combo.expired=\u5957\u9910\u4E0D\u5B58\u5728\uFF0C\u6216\u5DF2\u5931\u6548
yami.main.prod.wrong=\u4E3B\u5546\u54C1\u4FE1\u606F\u9519\u8BEF\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5
yami.select.matching.prod=\u8BF7\u9009\u62E9\u642D\u914D\u5546\u54C1
yami.select.required.matching.items=\u8BF7\u9009\u62E9\u5FC5\u9009\u642D\u914D\u5546\u54C1
yami.prod.package.cannot.empty=\u5957\u9910\u642D\u914D\u5546\u54C1\u5217\u8868\u4E0D\u80FD\u4E3A\u7A7A
yami.active.prod.cannot.add.cart=\u6D3B\u52A8\u5546\u54C1\u4E0D\u80FD\u52A0\u5165\u8D2D\u7269\u8F66
yami.active.prod.cannot.add.collection=\u6D3B\u52A8\u5546\u54C1\u4E0D\u80FD\u6DFB\u52A0\u6536\u85CF
yami.active.prod.cannot.buy=\u6D3B\u52A8\u5546\u54C1\u4E0D\u80FD\u5355\u72EC\u8D2D\u4E70
yami.combo.prod.already.exists=\u8D2D\u7269\u8F66\u4E2D\u5DF2\u5B58\u5728\u8BE5\u89C4\u683C\u4E0D\u540C\u642D\u914D\u7684\u5957\u9910\uFF0C \u8BF7\u52FF\u91CD\u590D\u52A0\u8D2D
yami.specification.already.exists.shopping.cart=\u8D2D\u7269\u8F66\u5DF2\u5B58\u5728\u8BE5\u89C4\u683C
yami.cn.reason.duplicate=\u4E2D\u6587\u539F\u56E0\u91CD\u590D\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165
yami.en.reason.duplicate=\u82F1\u6587\u539F\u56E0\u91CD\u590D\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165
yami.system.reason.not.delete=\u7CFB\u7EDF\u5185\u7F6E\u51FA\u5165\u5E93\u539F\u56E0\u4E0D\u80FD\u5220\u9664
yami.sku.price.not.change=\u53C2\u52A0\u4E86\u5957\u9910\u6216\u8D60\u54C1\u6D3B\u52A8\uFF0C\u65E0\u6CD5\u66F4\u6539\u4EF7\u683C\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u91CD\u8BD5
yami.sku.stockWarning.limit = \u5E93\u5B58\u9884\u8B66\u8D85\u8FC7\u6700\u5927\u503C
yami.combo.prod.not.delete=\u53C2\u52A0\u4EE5\u4E0B\u6D3B\u52A8\u7684\u5546\u54C1\u4E0D\u80FD\u88AB\u5220\u9664\uFF1A\u4F18\u60E0\u5957\u9910
yami.giveaway.prod.not.delete=\u53C2\u52A0\u4EE5\u4E0B\u6D3B\u52A8\u7684\u5546\u54C1\u4E0D\u80FD\u88AB\u5220\u9664\uFF1A\u8D60\u54C1
yami.sys.web.config.delete=\u4E0D\u80FD\u5220\u9664\u6FC0\u6D3B\u72B6\u6001\u7684\u914D\u7F6E
yami.imgs.length.then.max=imgs\u6570\u636E\u9519\u8BEF\uFF1A\u957F\u5EA6\u5927\u4E8E255
yami.seckill.invalid=\u8BE5\u79D2\u6740\u6D3B\u52A8\u5DF2\u5931\u6548
yami.not.ordinary.prod=\u4E0D\u662F\u666E\u901A\u5546\u54C1
yami.lack.permission.pre=\u60A8\u7F3A\u5C11
yami.lack.permission.suf=\u6A21\u5757\u7684\u6743\u9650
yami.refund.amount.check1=\u9000\u6B3E\u91D1\u989D\u6709\u8BEF\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165
yami.role.use.cannot.deleted=\u89D2\u8272\u4F7F\u7528\u4E2D\u4E0D\u80FD\u5220\u9664
yami.prod.platform.category.deleted=\u8BE5\u5E73\u53F0\u5206\u7C7B\u5DF2\u5220\u9664\uFF0C\u8BF7\u9009\u62E9\u65B0\u7684\u5206\u7C7B
yami.not.permission.modify.administrator.info=\u60A8\u6CA1\u6709\u6743\u9650\u4FEE\u6539\u7BA1\u7406\u5458\u4FE1\u606F
yami.index.img.reached.limit=\u8BE5\u7528\u6237\u7AEF\u7684\u8F6E\u64AD\u56FE\u5DF2\u8FBE\u5230\u6700\u5927\u6570\u91CF\uFF0C\u4E0D\u80FD\u518D\u8FDB\u884C\u65B0\u589E\u64CD\u4F5C
yami.shopCart.prod.error=\u9884\u552E/\u865A\u62DF/\u6D3B\u52A8\u5546\u54C1\u4E0D\u80FD\u52A0\u5165\u8D2D\u7269\u8F66\uFF01
yami.sku.cannot.empty=sku\u5217\u8868\u4E0D\u80FD\u4E3A\u7A7A
yami.signingAuditing.auditInformation.notFound=\u627E\u4E0D\u5230\u8BE5\u5BA1\u6838\u4FE1\u606F\uFF0C\u8BF7\u5237\u65B0\u9875\u9762
yami.Auditing.applicationInfo.notFound=\u627E\u4E0D\u5230\u6B64\u7533\u8BF7\u4FE1\u606F\uFF0C\u8BF7\u5237\u65B0\u9875\u9762
yami.signingAuditing.categorySigningInformation.notFound=\u8BE5\u5206\u7C7B\u7B7E\u7EA6\u4FE1\u606F\u4E0D\u5B58\u5728\u6216\u9519\u8BEF\uFF0C\u8BF7\u5237\u65B0\u9875\u9762
yami.invoice.categoryId.notNull=\u5206\u7C7Bid\u4E0D\u80FD\u4E3A\u7A7A
yami.invoice.brandId.notNull=\u54C1\u724Cid\u4E0D\u80FD\u4E3A\u7A7A
yami.order.devType.notMatch=\u5BFC\u5165\u7684\u914D\u9001\u65B9\u5F0F\u4E0E\u8BA2\u5355\u7684\u914D\u9001\u65B9\u5F0F\u4E0D\u4E00\u81F4
yami.out.orderNumber=\u5916\u90E8\u8BA2\u5355\u6D41\u6C34\u53F7
yami.pay.status=\u652F\u4ED8\u72B6\u6001
yami.pay.score=\u652F\u4ED8\u79EF\u5206
yami.pay.amount=\u652F\u4ED8\u91D1\u989D
yami.pay.time=\u652F\u4ED8\u65F6\u95F4
yami.order.pay=\u5DF2\u652F\u4ED8
yami.order.no.paid=\u672A\u652F\u4ED8
yami.pay.info.reportTitle=\u6536\u5165\u5BF9\u8D26\u660E\u7EC6\u62A5\u8868
yami.refund.info.reportTitle=\u9000\u6B3E\u5BF9\u8D26\u660E\u7EC6\u62A5\u8868
yami.account.info.reportTitle=\u5BF9\u8D26\u660E\u7EC6\u62A5\u8868
yami.pay.no=\u652F\u4ED8\u5355\u53F7
yami.refund.no=\u9000\u6B3E\u5355\u53F7
yami.refund.status=\u9000\u6B3E\u72B6\u6001
yami.refund.time=\u9000\u6B3E\u65F6\u95F4
yami.refund.finish=\u5DF2\u9000\u6B3E
yami.message.leng.exceed.limit=\u6D88\u606F\u5185\u5BB9\u957F\u5EA6\u8D85\u51FA\u9650\u5236
yami.order.is.closed=\u8BA2\u5355\u5DF2\u5173\u95ED
yami.deliverySum.exceed.stocks=\u51FA\u5E93\u6570\u8D85\u51FA\u5E93\u5B58\u6570
yami.shop.pay.info.update.error=\u652F\u4ED8\u4FE1\u606F\u66F4\u65B0\u5931\u8D25
yami.prod.import.virtualRemark.notValid=\u865A\u62DF\u5546\u54C1\u7559\u8A00\u683C\u5F0F\u4E0D\u6B63\u786E
yami.sensitive.words.reenter=\u5B58\u5728\u654F\u611F\u8BCD\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165
yami.prod.status.error.Please.exit.and.try.again=\u5546\u54C1\u72B6\u6001\u4E0D\u6B63\u786E\uFF0C\u8BF7\u9000\u51FA\u91CD\u8BD5
yami.finance.form.excel=\u8BF7\u9009\u62E9\u5BFC\u51FA\u62A5\u8868\u7684\u4EA4\u6613\u65F6\u95F4
yami.shop.wallet.log.excel=\u5E97\u94FA\u7ED3\u7B97\u660E\u7EC6\u8868
yami.Shipping.amount.error=\u8FD0\u8D39\u91D1\u989D\u4E0D\u80FD\u5C0F\u4E8E0
yami.balance.out.error=\u4F59\u989D\u4E0D\u5F97\u8D85\u8FC7999999999.99
yami.score.out.error=\u79EF\u5206\u4E0D\u5F97\u8D85\u8FC7100000000
yami.trans.amount.not.null=\u7EDF\u4E00\u8FD0\u8D39\u65F6\u8FD0\u8D39\u4E0D\u80FD\u4E3A\u7A7A
yami.delivery.name.is.same=\u4E0E\u7CFB\u7EDF\u5185\u7F6E\u6A21\u677F\u540D\u79F0\u91CD\u590D\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165
yami.delivery.error=\u8BF7\u9009\u62E9\u53EF\u914D\u9001\u533A\u57DF
yami.delivery.over=\u5F53\u524D\u533A\u57DF\u4E0D\u652F\u6301\u914D\u9001
yami.cannot.used.score.payment=\u652F\u4ED8\u91D1\u989D\u5927\u4E8E0\u7684\u8BA2\u5355\uFF0C\u4E0D\u80FD\u4F7F\u7528\u79EF\u5206\u652F\u4ED8
yami.combo.price.excessive=\u5957\u9910\u603B\u91D1\u989D\u8FC7\u5927\uFF0C\u8BF7\u5408\u7406\u8BBE\u7F6E
yami.order.prod.count.limit=\u4E0B\u5355\u5546\u54C1\u6570\u91CF\u4E0D\u80FD\u5C0F\u4E8E1
yami.product.has.created.seckill=\u8BE5\u5546\u54C1\u5DF2\u521B\u5EFA\u79D2\u6740\u6D3B\u52A8\uFF0C\u8BF7\u52FF\u91CD\u590D\u63D0\u4EA4
yami.pcdn.error=\u7cfb\u7edf\u7e41\u5fd9\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5
yami.pcdn.assets.freeze=\u51bb\u7ed3\u6570\u91cf\u5fc5\u987b\u5728100\u52309999\u4e4b\u95f4
yami.user.assets.lucky.coin.balance=\u5e78\u8fd0\u5e01\u4f59\u989d\u4e0d\u8db3
yami.user.assets.lucky.coin.freeze=\u51bb\u7ed3\u5e01\u4f5c\u4e3a\u53c2\u6570\u4e3a\u7a7a
yami.user.device.not.exist=\u7528\u6237\u8bbe\u5907\u4e0d\u5b58\u5728
yami.pcdn.device.bound=\u8be5\u8bbe\u5907\u5df2\u88ab\u7ed1\u5b9a
yami.pcdn.device.delete=\u8be5\u8bbe\u5907\u5df2\u88ab\u5220\u9664
yami.pcdn.device.token=\u8bf7\u8bbe\u7f6e\u83b7\u53d6token\u7684\u914d\u7f6e\u6587\u4ef6
yami.pcdn.device.id.null=\u8bbe\u5907id\u4e3a\u7a7a
yami.pcdn.device.userId.null=\u7528\u6237id\u4e3a\u7a7a
yami.pcdn.device.binding.error=\u8be5\u8bbe\u5907\u5df2\u7ecf\u7ed1\u5b9a\u5728\u4f60\u7684\u8d26\u53f7
yami-shop-common/src/main/resources/ip2region.xdb
Binary files differ
yami-shop-coupon/pom.xml
New file
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>yami-shop</artifactId>
        <groupId>com.yami.shop</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>yami-shop-coupon</artifactId>
    <description>商城优惠券模块</description>
    <packaging>pom</packaging>
    <modules>
        <module>yami-shop-coupon-api</module>
        <module>yami-shop-coupon-platform</module>
        <module>yami-shop-coupon-multishop</module>
        <module>yami-shop-coupon-common</module>
    </modules>
</project>
yami-shop-coupon/yami-shop-coupon-api/pom.xml
New file
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>yami-shop-coupon</artifactId>
        <groupId>com.yami.shop</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>yami-shop-coupon-api</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-coupon-common</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-security-api</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
    </dependencies>
</project>
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/config/SwaggerConfiguration.java
New file
@@ -0,0 +1,38 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.api.config;
import lombok.AllArgsConstructor;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * 优惠券
 * @author lanhai
 */
@Configuration("couponSwaggerConfiguration")
@AllArgsConstructor
public class SwaggerConfiguration {
    @Bean
    public GroupedOpenApi couponRestApi() {
        return GroupedOpenApi.builder()
                .group("优惠券接口")
                .packagesToScan("com.yami.shop.coupon.api.controller")
                .pathsToMatch("/**")
                .build();
    }
}
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/controller/CouponController.java
New file
@@ -0,0 +1,159 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.api.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.app.dto.CouponDto;
import com.yami.shop.bean.app.dto.ProductDto;
import com.yami.shop.bean.enums.CouponProdType;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.coupon.common.model.Coupon;
import com.yami.shop.coupon.common.model.CouponProd;
import com.yami.shop.coupon.common.service.CouponService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.Operation;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * 优惠券接口
 *
 * @author lanhai
 */
@RestController
@RequestMapping("/coupon")
@Tag(name = "优惠券接口")
public class CouponController {
    @Autowired
    private CouponService couponService;
    @Autowired
    private MapperFacade mapperFacade;
    @GetMapping("/listShopCoupon")
    @Operation(summary = "查看一店铺的所有优惠券" , description = "通过店铺id(shopId)获取该店优惠券")
    @Parameters({
            @Parameter(name = "shopId", description = "店铺ID" , required = true)
    })
    public ServerResponseEntity<List<CouponDto>> listShopCoupon(@RequestParam(value = "shopId") Long shopId) {
        List<Coupon> couponList = couponService.listPutonByShopId(shopId);
        List<CouponDto> couponDtos = mapperFacade.mapAsList(couponList, CouponDto.class);
        return ServerResponseEntity.success(couponDtos);
    }
    @GetMapping("/listByProdId")
    @Operation(summary = "获取商品可用的优惠券列表" , description = "获取该商品可用的优惠券列表")
    @Parameters({
            @Parameter(name = "shopId", description = "店铺id" , required = true),
            @Parameter(name = "prodId", description = "商品id" , required = true)
    })
    public ServerResponseEntity<List<CouponDto>> listByProdId(Long shopId, Long prodId) {
        // 获取已投放优惠券
        List<Coupon> couponList = couponService.listPutonByShopId(shopId);
        // 过滤商品
        couponList = couponList.stream().filter(a -> {
            boolean flag = true;
            if (a.getGetWay() == null) {
                // 如果getWay为空,默认当成0处理
                a.setGetWay(0);
            } else if (a.getGetWay() == 1) {
                // 不是用户直接领取的优惠券,直接不显示该优惠券
                return false;
            }
            //过滤指定商品不参与
            if (Objects.equals(a.getSuitableProdType(), CouponProdType.PROD_NO_IN.value())) {
                for (CouponProd couponProd : a.getCouponProds()) {
                    if (Objects.equals(couponProd.getProdId(), prodId)) {
                        flag = false;
                        break;
                    }
                }
            }
            //过滤指定商品参与
            else if (Objects.equals(a.getSuitableProdType(), CouponProdType.PROD_IN.value())) {
                flag = false;
                for (CouponProd couponProd : a.getCouponProds()) {
                    if (Objects.equals(couponProd.getProdId(), prodId)) {
                        flag = true;
                        break;
                    }
                }
            }
            return flag;
        }).collect(Collectors.toList());
        List<CouponDto> couponDtos = mapperFacade.mapAsList(couponList, CouponDto.class);
        return ServerResponseEntity.success(couponDtos);
    }
    @GetMapping("/prodListByCouponId")
    @Operation(summary = "获取优惠券可用的商品列表" , description = "获取优惠券可用的商品列表")
    @Parameter(name = "couponId", description = "优惠券id" , required = true)
    public ServerResponseEntity<IPage<ProductDto>> prodListByCouponId(PageParam<ProductDto> page, @RequestParam("couponId") Long couponId) {
        if (couponId <= 0) {
            page.setRecords(Collections.emptyList());
            return ServerResponseEntity.success(page);
        }
        Coupon coupon = couponService.getById(couponId);
        if (Objects.isNull(coupon) || coupon.getOverdueStatus() != 1) {
            page.setRecords(Collections.emptyList());
            return ServerResponseEntity.success(page);
        }
        IPage<ProductDto> productPage = couponService.prodListByCoupon(page, coupon, I18nMessage.getDbLang());
        return ServerResponseEntity.success(productPage);
    }
    @GetMapping("/couponScorePage")
    @Operation(summary = "积分优惠券列表" , description = "获取积分商城可换的优惠券列表")
    public ServerResponseEntity<IPage<Coupon>> couponScorePage(PageParam<Coupon> page) {
        IPage<Coupon> couponDtos = couponService.page(page, new LambdaQueryWrapper<Coupon>()
                .eq(Coupon::getOverdueStatus, 1)
                .eq(Coupon::getPutonStatus, 1)
                .eq(Coupon::getIsScoreType, 1));
        return ServerResponseEntity.success(couponDtos);
    }
    @GetMapping("/couponById")
    @Operation(summary = "获取一条优惠券信息" , description = "通过id获取对应优惠券")
    @Parameter(name = "couponId", description = "优惠券id" , required = true)
    public ServerResponseEntity<Coupon> getCouponById(Long couponId) {
        Coupon coupon = couponService.getById(couponId);
        return ServerResponseEntity.success(coupon);
    }
    @GetMapping("/getCouponPage")
    @Operation(summary = "商品券列表(商家优惠券),游客访问" , description = "获取商品券列表(指定商品可用优惠券),游客访问")
    public ServerResponseEntity<IPage<CouponDto>> getCouponList(PageParam<CouponDto> page) {
        IPage<CouponDto> couponDto = couponService.getCouponList(page);
        return ServerResponseEntity.success(couponDto);
    }
    @GetMapping("/generalCouponList")
    @Operation(summary = "通用券列表(平台优惠券)" , description = "获取通用券列表")
    public ServerResponseEntity<List<CouponDto>> generalCouponList() {
        List<CouponDto> couponList = couponService.generalCouponList();
        return ServerResponseEntity.success(couponList);
    }
}
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/controller/MyCouponController.java
New file
@@ -0,0 +1,129 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.api.controller;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.app.dto.CouponDto;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.coupon.common.model.Coupon;
import com.yami.shop.coupon.common.model.CouponUser;
import com.yami.shop.coupon.common.service.CouponService;
import com.yami.shop.coupon.common.service.CouponUserService;
import com.yami.shop.security.api.util.SecurityUtils;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
 * 我的优惠券接口
 *
 * @author lanhai
 */
@RestController
@RequestMapping("/p/myCoupon")
@Tag(name = "我的优惠券接口")
@AllArgsConstructor
public class MyCouponController {
    private CouponService couponService;
    private CouponUserService couponUserService;
    @GetMapping("/listCouponIds")
    @Operation(summary = "查看用户拥有的所有优惠券id" , description = "查看用户拥有的所有优惠券id")
    public ServerResponseEntity<List<CouponDto>> list() {
        String userId = SecurityUtils.getUser().getUserId();
        List<CouponDto> coupons = couponService.listCouponIdsByUserId(userId);
        return ServerResponseEntity.success(coupons);
    }
    @PostMapping("/receive")
    @Operation(summary = "领取优惠券接口" , description = "领取优惠券接口")
    @Parameter(name = "couponId", description = "优惠券ID" , required = true)
    public ServerResponseEntity<String> receive(@RequestBody Long couponId) {
        String userId = SecurityUtils.getUser().getUserId();
        Coupon coupon = couponService.getById(couponId);
        couponService.receive(coupon, userId);
        // 领取优惠券成功
        return ServerResponseEntity.success(I18nMessage.getMessage("yami.coupon.receive.success"));
    }
    @GetMapping("/getMyCouponsStatusCount")
    @Operation(summary = "获取优惠券个数" , description = "获取各个状态下的优惠券个数")
    public ServerResponseEntity<Map<String, Long>> getCouponCountByStatus() {
        String userId = SecurityUtils.getUser().getUserId();
        Map<String, Long> couponCount = couponService.getCouponCountByStatus(userId);
        return ServerResponseEntity.success(couponCount);
    }
    @GetMapping("/getCouponList")
    @Operation(summary = "通过状态查看用户的优惠券列表信息" , description = "通过状态查看用户的优惠券列表信息,优惠券状态 0:已过期 1:未使用 2:使用过")
    @Parameter(name = "status", description = "优惠券状态 0:失效 1:有效 2:使用过" , required = true)
    public ServerResponseEntity<IPage<CouponDto>> getCouponList(PageParam<CouponDto> page, @RequestParam("status") Integer status) {
        String userId = SecurityUtils.getUser().getUserId();
        IPage<CouponDto> couponDtoList = couponService.getCouponListByStatus(page, userId, status);
        return ServerResponseEntity.success(couponDtoList);
    }
    @Deprecated
    @DeleteMapping("/deleteCoupon/{couponId}")
    @Operation(summary = "删除用户优惠券" , description = "通过优惠券id删除用户优惠券")
    @Parameter(name = "couponId", description = "优惠券Id" , required = true)
    public ServerResponseEntity<String> deleteCoupon(@PathVariable("couponId") Long couponId) {
        String userId = SecurityUtils.getUser().getUserId();
        couponService.deleteUserCouponByCouponId(userId, couponId);
        // 删除成功
        return ServerResponseEntity.success(I18nMessage.getMessage("yami.delete.successfully"));
    }
    @DeleteMapping("/delCoupon/{couponUserId}")
    @Operation(summary = "删除用户优惠券" , description = "通过优惠券关联id删除用户优惠券")
    @Parameter(name = "couponUserId", description = "优惠券关联id" , required = true)
    public ServerResponseEntity<String> deleteCouponById(@PathVariable("couponUserId") Long couponUserId) {
        String userId = SecurityUtils.getUser().getUserId();
        CouponUser couponUser = new CouponUser();
        couponUser.setCouponUserId(couponUserId);
        couponUser.setIsDelete(1);
        couponUserService.update(couponUser, new LambdaUpdateWrapper<CouponUser>()
                .eq(CouponUser::getCouponUserId, couponUserId).eq(CouponUser::getUserId, userId));
        // 删除成功
        return ServerResponseEntity.success(I18nMessage.getMessage("yami.delete.successfully"));
    }
    @GetMapping("/generalCouponList")
    @Operation(summary = "通用券列表(平台优惠券)" , description = "获取通用券列表")
    public ServerResponseEntity<List<CouponDto>> generalCouponList() {
        String userId = SecurityUtils.getUser().getUserId();
        List<CouponDto> couponList = couponService.generalCouponList(userId);
        return ServerResponseEntity.success(couponList);
    }
//    @GetMapping("/prodCouponList")
//    @Operation(summary = "商品券列表" , description = "获取商品券列表(指定商品可用优惠券)")
//    public ServerResponseEntity<IPage<CouponDto>> prodCouponList(PageParam<CouponDto> page) {
//        String userId = SecurityUtils.getUser().getUserId();
//        return ServerResponseEntity.success(couponService.pageProdCoupon(page, userId));
//    }
    @GetMapping("/getCouponPage")
    @Operation(summary = "商品券列表(商家优惠券)" , description = "获取商品券列表(指定商品可用优惠券)")
    public ServerResponseEntity<IPage<CouponDto>> getCouponList(PageParam<CouponDto> page) {
        String userId = SecurityUtils.getUser().getUserId();
        IPage<CouponDto> couponDto = couponService.getCouponList(page, userId);
        return ServerResponseEntity.success(couponDto);
    }
}
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/listener/SubmitOrderActivityListener.java
New file
@@ -0,0 +1,88 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.api.listener;
import cn.hutool.core.collection.CollectionUtil;
import com.yami.shop.bean.app.dto.CouponOrderDto;
import com.yami.shop.bean.app.dto.ShopCartOrderDto;
import com.yami.shop.bean.app.dto.ShopCartOrderMergerDto;
import com.yami.shop.bean.event.SubmitOrderActivityEvent;
import com.yami.shop.bean.order.SubmitOrderActivityOrder;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.coupon.common.dao.CouponUserMapper;
import com.yami.shop.security.api.util.SecurityUtils;
import lombok.AllArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
 * 确认订单信息时的优惠券的相关操作,计算优惠券 优惠金额
 *
 * @author LGH
 */
@Component("checkCouponStatusListener")
@AllArgsConstructor
public class SubmitOrderActivityListener {
    private final CouponUserMapper couponUserMapper;
    /**
     * 将店铺下的所有商品归属到该店铺的购物车当中
     *
     * @param event#ShopCartOrderMergerDto 组装完成的商品订单信息
     * @return 是否继续组装
     */
    @EventListener(SubmitOrderActivityEvent.class)
    @Order(SubmitOrderActivityOrder.COUPON)
    public void checkCouponStatusListener(SubmitOrderActivityEvent event) {
        String userId = SecurityUtils.getUser().getUserId();
        ShopCartOrderMergerDto shopCartOrderMergerDto = event.getShopCartOrderMergerDto();
        //店铺优惠券
        List<List<CouponOrderDto>> shopCoupons = shopCartOrderMergerDto.getShopCartOrders().stream().filter((ShopCartOrderDto shopCartOrderDto) ->CollectionUtil.isNotEmpty(shopCartOrderDto.getCoupons())).map(ShopCartOrderDto::getCoupons).collect(Collectors.toList());
        List<Long> couponUserIds = new ArrayList<>();
        if(CollectionUtil.isEmpty(shopCartOrderMergerDto.getCoupons()) && CollectionUtil.isEmpty(shopCoupons)){
            return;
        }
        if(CollectionUtil.isNotEmpty(shopCartOrderMergerDto.getCoupons())){
            for (CouponOrderDto coupon : shopCartOrderMergerDto.getCoupons()) {
                if(coupon.isChoose()){
                    couponUserIds.add(coupon.getCouponUserId());
                    break;
                }
            }
        }
        if(CollectionUtil.isNotEmpty(shopCoupons)){
            for (ShopCartOrderDto shopCartOrderDto : shopCartOrderMergerDto.getShopCartOrders()) {
                for (CouponOrderDto coupon : shopCartOrderDto.getCoupons()) {
                    if(coupon.isChoose()){
                        couponUserIds.add(coupon.getCouponUserId());
                        break;
                    }
                }
            }
        }
        if(CollectionUtil.isEmpty(couponUserIds)){
            return;
        }
        int num = couponUserMapper.countNormalByCouponUserId(couponUserIds,userId);
        if(num < couponUserIds.size()){
            throw new YamiShopBindException("yami.order.coupon.expire.check");
        }
    }
}
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/listener/SubmitOrderListener.java
New file
@@ -0,0 +1,96 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.api.listener;
import com.yami.shop.coupon.common.dao.CouponUserMapper;
import com.yami.shop.coupon.common.service.CouponUseRecordService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
/**
 * 优惠券提交订单监听
 * @author lanhai
 */
@Component("couponSubmitOrderListener")
@AllArgsConstructor
public class SubmitOrderListener {
    private final CouponUserMapper couponUserMapper;
    private final CouponUseRecordService couponUseRecordService;
//
//    /**
//     * 修改优惠券为已使用状态
//     */
//    @EventListener(SubmitOrderEvent.class)
//    @Order(SubmitOrderOrder.COUPON)
//    public void couponSubmitOrderListener(SubmitOrderEvent event) {
//
//        //待改状态的优惠列表
//        List<Long> userCouponIds = Lists.newArrayList();
//
//        List<CouponUseRecord> couponUseRecordList = Lists.newArrayList();
//        List<ShopCartOrderDto> shopCartOrders = event.getMergerOrder().getShopCartOrders();
//
//
//        if(CollectionUtils.isEmpty(shopCartOrders)){
//            return ;
//        }
//        // 订单号集合
//        StringBuilder orderNumbers = new StringBuilder(100);
//
//        for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
//            orderNumbers.append(shopCartOrder.getOrderNumber()).append(StrUtil.COMMA);
//            List<CouponOrderDto> shopCartOrderCoupons = shopCartOrder.getCoupons();
//
//            if (CollectionUtils.isEmpty(shopCartOrderCoupons)) {
//                continue;
//            }
//            // 聚合店铺优惠券
//            addCouponUseRecordList(shopCartOrderCoupons, shopCartOrder.getOrderNumber(), couponUseRecordList, userCouponIds);
//        }
//        orderNumbers.deleteCharAt(orderNumbers.length() - 1);
//        // 聚合平台优惠券
//        addCouponUseRecordList(event.getMergerOrder().getCoupons(),orderNumbers.toString(), couponUseRecordList, userCouponIds);
//
//
//        if (CollectionUtils.isNotEmpty(userCouponIds)) {
//            // 批量更新用户优惠券使用状态
//            couponUserMapper.batchUpdateUserCouponStatus(2, userCouponIds);
//        }
//        if (CollectionUtils.isNotEmpty(couponUseRecordList)) {
//            // 批量插用户优惠券使用记录
//            couponUseRecordService.addCouponUseRecode(couponUseRecordList);
//        }
//
//    }
//
//    private void addCouponUseRecordList(List<CouponOrderDto> shopCartOrderCoupons, String orderNumber,List<CouponUseRecord> couponUseRecordList, List<Long> userCouponIds){
//        if (CollectionUtils.isEmpty(shopCartOrderCoupons)) {
//            return;
//        }
//
//        for (CouponOrderDto couponOrderDto : shopCartOrderCoupons) {
//            if (couponOrderDto.isChoose() && couponOrderDto.isCanUse()) {
//                CouponUseRecord couponUseRecord = new CouponUseRecord();
//                couponUseRecord.setAmount(couponOrderDto.getReduceAmount());
//                // 获取用户优惠券id
//                couponUseRecord.setCouponUserId(couponOrderDto.getCouponUserId());
//                couponUseRecord.setUserId(SecurityUtils.getUser().getUserId());
//                couponUseRecord.setOrderNumber(orderNumber);
//                couponUseRecord.setUseTime(new Date());
//                //优惠券记录为冻结状态
//                couponUseRecord.setStatus(1);
//                couponUseRecordList.add(couponUseRecord);
//                userCouponIds.add(couponOrderDto.getCouponUserId());
//            }
//        }
//    }
}
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/manager/impl/CouponConfirmOrderManagerImpl.java
New file
@@ -0,0 +1,122 @@
/*
 * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.api.manager.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.bean.param.ChooseCouponParam;
import com.yami.shop.bean.param.PlatformChooseCouponParam;
import com.yami.shop.common.util.Arith;
import com.yami.shop.coupon.api.util.ChooseCouponHelper;
import com.yami.shop.coupon.common.service.CouponService;
import com.yami.shop.manager.CouponConfirmOrderManager;
import com.yami.shop.security.api.util.SecurityUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.stream.Collectors;
/**
 * 确认订单信息时的优惠券的相关操作,计算优惠券 优惠金额
 *
 * @author LGH
 */
@Component
@AllArgsConstructor
public class CouponConfirmOrderManagerImpl implements CouponConfirmOrderManager {
    private final CouponService couponService;
    @Override
    public List<ShopCartDto> chooseShopCoupon(ChooseCouponParam param) {
        String userId = SecurityUtils.getUser().getUserId();
        List<ShopCartDto> shopCarts = param.getShopCarts();
        for (ShopCartDto shopCart : shopCarts) {
            List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCart.getShopCartItemDiscounts();
            List<ShopCartItemDto> shopCartItems = new ArrayList<>();
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
                shopCartItems.addAll(shopCartItemDiscount.getShopCartItems());
            }
            // 因为经过满减,实际金额的顺序已经变了
            shopCartItems = shopCartItems.stream().sorted(Comparator.comparingDouble(ShopCartItemDto::getActualTotal)).collect(Collectors.toList());
            // 获取用户有效的优惠券
            List<CouponOrderDto> shopCoupons = couponService.getCouponListByShopIds(userId, shopCart.getShopId());
            // 用户选中的所有优惠券
            List<Long> couponUserIds = param.getCouponUserIds();
            Integer userChangeCoupon = param.getUserChangeCoupon();
            ChooseCouponHelper chooseCouponHelper = new ChooseCouponHelper(shopCartItems, shopCoupons, couponUserIds, userChangeCoupon).invoke();
            if (chooseCouponHelper.getChooseCoupon() != null) {
                double couponReduce = chooseCouponHelper.getCouponReduce();
                // 最后组装订单信息
                shopCart.setCouponReduce(Math.min(couponReduce, shopCart.getActualTotal()));
                shopCart.setActualTotal(Arith.sub(shopCart.getActualTotal(), shopCart.getCouponReduce()));
                shopCart.setShopReduce(Arith.add(shopCart.getShopReduce(), shopCart.getCouponReduce()));
            }
            shopCart.setCoupons(shopCoupons);
        }
        return shopCarts;
    }
    @Override
    public ShopCartOrderMergerDto choosePlatformCoupon(PlatformChooseCouponParam param) {
        String userId = SecurityUtils.getUser().getUserId();
        ShopCartOrderMergerDto shopCartOrderMergerVO = param.getShopCartOrderMergerDto();
        // 获取用户可用平台优惠券
        List<CouponOrderDto> couponList = couponService.getCouponListByShopIds(userId, 0L);
        if (CollectionUtil.isEmpty(couponList)) {
            return shopCartOrderMergerVO;
        }
        // 完整的订单信息
        // 订单项目
        List<ShopCartItemDto> shopAllShopCartItems = new ArrayList<>();
        List<ShopCartOrderDto> shopCartOrders = shopCartOrderMergerVO.getShopCartOrders();
        for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
            List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCartOrder.getShopCartItemDiscounts();
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
                shopAllShopCartItems.addAll(shopCartItemDiscount.getShopCartItems());
            }
        }
        // 因为经过满减,实际金额的顺序已经变了
        shopAllShopCartItems = shopAllShopCartItems.stream().sorted(Comparator.comparingDouble(ShopCartItemDto::getActualTotal)).collect(Collectors.toList());
        ChooseCouponHelper chooseCouponHelper = new ChooseCouponHelper(shopAllShopCartItems, couponList, param.getCouponUserIds(), param.getUserChangeCoupon()).invoke();
        if (chooseCouponHelper.getChooseCoupon() != null) {
            double couponReduce = chooseCouponHelper.getCouponReduce();
            Map<Long, Double> shopReduceMap = chooseCouponHelper.getShopReduceMap();
            for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
                Double couponAmount = shopReduceMap.get(shopCartOrder.getShopId());
                shopCartOrder.setPlatformCouponReduce(couponAmount);
                couponAmount = Objects.isNull(shopCartOrder.getPlatformAmount()) ? couponAmount : Arith.add(shopCartOrder.getPlatformAmount(), couponAmount);
                shopCartOrder.setPlatformAmount(couponAmount);
                shopCartOrder.setActualTotal(Arith.sub(shopCartOrder.getActualTotal(), shopCartOrder.getPlatformCouponReduce()));
                shopCartOrder.setShopReduce(Arith.add(shopCartOrder.getShopReduce(), shopCartOrder.getPlatformCouponReduce()));
            }
            shopCartOrderMergerVO.setOrderReduce(Arith.add(shopCartOrderMergerVO.getOrderReduce(), couponReduce));
            shopCartOrderMergerVO.setActualTotal(Arith.sub(shopCartOrderMergerVO.getActualTotal(), couponReduce));
        }
        shopCartOrderMergerVO.setCoupons(couponList);
        return shopCartOrderMergerVO;
    }
}
yami-shop-coupon/yami-shop-coupon-api/src/main/java/com/yami/shop/coupon/api/util/ChooseCouponHelper.java
New file
@@ -0,0 +1,321 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.api.util;
import cn.hutool.core.collection.CollectionUtil;
import com.yami.shop.bean.app.dto.CouponOrderDto;
import com.yami.shop.bean.app.dto.ProductItemDto;
import com.yami.shop.bean.app.dto.ShopCartItemDto;
import com.yami.shop.bean.enums.CouponProdType;
import com.yami.shop.bean.enums.CouponType;
import com.yami.shop.common.util.Arith;
import org.apache.commons.collections4.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
 * 协助优惠券进行选择
 *
 * @author LGH
 */
public class ChooseCouponHelper {
    /**
     * 购物项
     */
    private List<ShopCartItemDto> shopCartItems;
    /**
     * 含有的优惠券列表
     */
    private final List<CouponOrderDto> shopCoupons;
    /**
     * 选中的优惠券id
     */
    private List<Long> couponUserIds;
    /**
     * 用户是否选中优惠券
     */
    private final Integer userChangeCoupon;
    /**
     * 选中的优惠券
     */
    private CouponOrderDto chooseCoupon;
    /**
     * 可用优惠券的商品实际金额(商品实际金额 - 商品分摊金额)
     */
    private double prodCanUseCouponActualTotal;
    /**
     * 优惠金额
     */
    private double couponReduce;
    /**
     * 优惠金额参与的商品数量
     */
    private Integer reduceNum;
    /**
     * 优惠金额
     */
    private double chooseCouponProdAmount;
    /**
     * 优惠券在订单中的优惠金额
     */
    private double couponInOrderAmount;
    /**
     * 优惠金额关联店铺map
     */
    private final Map<Long, Double> shopReduceMap = new HashMap<>(12);
    public ChooseCouponHelper(List<ShopCartItemDto> shopCartItems, List<CouponOrderDto> shopCoupons, List<Long> couponUserIds, Integer userChangeCoupon) {
        this.shopCartItems = shopCartItems;
        this.shopCoupons = shopCoupons;
        this.couponUserIds = couponUserIds;
        this.userChangeCoupon = userChangeCoupon;
    }
    public CouponOrderDto getChooseCoupon() {
        return chooseCoupon;
    }
    public Map<Long, Double> getShopReduceMap() {
        return shopReduceMap;
    }
    public double getCouponReduce() {
        return this.couponReduce;
    }
    public ChooseCouponHelper invoke() {
        // 没有平台优惠券直接返回
        if (CollectionUtils.isEmpty(shopCartItems)) {
            return this;
        }
        // 用户选中的关于该店铺的优惠券,一家店只能选择一张优惠券
        chooseCoupon = null;
        reduceNum = 0;
        if (Objects.isNull(couponUserIds)) {
            couponUserIds = new ArrayList<>();
        }
        // 可用优惠券的商品实际金额(商品实际金额 - 商品分摊金额)
        prodCanUseCouponActualTotal = 0.0;
        Date now = new Date();
        CouponOrderDto firstAvailableCoupon = null;
//        CouponOrderDto maxReduceChooseCoupon= null;
//        Double maxChooseCouponProdAmount = 0.00;
//        Double maxReduce=Double.MAX_VALUE;
        for (CouponOrderDto shopCoupon : shopCoupons) {
            if (shopCoupon.getStartTime().getTime() > now.getTime() || shopCoupon.getEndTime().getTime() < now.getTime()) {
                continue;
            }
            // 该优惠券关联的商品id
            List<Long> prodIds = shopCoupon.getProdIds();
            // 可用优惠券的商品实际金额(商品实际金额 - 商品分摊金额)
            prodCanUseCouponActualTotal = 0.0;
            for (ShopCartItemDto shopCartItem : shopCartItems) {
                // 套餐不参与优惠券活动
                if (Objects.nonNull(shopCartItem.getComboId()) && shopCartItem.getComboId() != 0) {
                    continue;
                }
                shopCartItem.setIsShareReduce(0);
                // 该商品是否在该优惠券可用
                boolean isCouponsProd = isCouponsProd(shopCartItem.getProdId(), prodIds, shopCoupon.getSuitableProdType());
                if (isCouponsProd) {
                    shopCartItem.setIsShareReduce(1);
                    prodCanUseCouponActualTotal = Arith.add(prodCanUseCouponActualTotal, shopCartItem.getActualTotal());
                }
            }
            Date date = new Date();
            // 如果该商品实际总金额大于等于优惠券最低使用金额,并且开始时间大于优惠券的使用时间,则优惠券可用
            if (prodCanUseCouponActualTotal >= shopCoupon.getCashCondition() && shopCoupon.getStartTime().getTime() < date.getTime()) {
                // 将优惠券标记为可用状态
                shopCoupon.setCanUse(true);
                if (Objects.nonNull(chooseCoupon)) {
                    continue;
                }
                // 折扣券的优惠金额要根据订单金额实时计算
                if (CouponType.C2D.value().equals(shopCoupon.getCouponType())) {
                    double reduceMoney = Arith.roundByBanker(Arith.sub(prodCanUseCouponActualTotal, Arith.div(Arith.mul(prodCanUseCouponActualTotal,
                            shopCoupon.getCouponDiscount()), 10)), 2);
                    shopCoupon.setReduceAmount(reduceMoney);
                }
                // 聚合 用户选中的关于该店铺的优惠券
                if (couponUserIds.contains(shopCoupon.getCouponUserId())) {
                    chooseCoupon = shopCoupon;
                    chooseCouponProdAmount = prodCanUseCouponActualTotal;
                }
                // 记录第一张可用优惠券
                if (firstAvailableCoupon == null) {
                    firstAvailableCoupon = shopCoupon;
                }
//                // 如果用户没有选择优惠券,系统默认选择一张优惠最大的可用优惠券
//                else if (chooseCoupon == null && !Objects.equals(userChangeCoupon, 1) && shopCoupon.getReduceAmount() < maxReduce) {
//                    maxReduce = shopCoupon.getReduceAmount();
//                    maxReduceChooseCoupon = shopCoupon;
//                    maxChooseCouponProdAmount = Arith.sub(prodCanUseCouponActualTotal,maxReduce);
//                }
            }
        }
        // 没选择优惠券,默认选择第一张可用的优惠券
        if (chooseCoupon == null
                && firstAvailableCoupon != null
                && !Objects.equals(userChangeCoupon, 1)) {
            chooseCoupon = firstAvailableCoupon;
            chooseCouponProdAmount = Arith.sub(prodCanUseCouponActualTotal, chooseCoupon.getReduceAmount());
//            chooseCoupon = maxReduceChooseCoupon;
//            chooseCouponProdAmount = maxChooseCouponProdAmount;
        }
        for (CouponOrderDto shopCoupon : shopCoupons) {
            // 该优惠券关联的商品id
            List<Long> prodIds = shopCoupon.getProdIds();
            if (Objects.nonNull(chooseCoupon) && !Objects.equals(shopCoupon.getCouponUserId(), chooseCoupon.getCouponUserId())) {
                continue;
            }
            for (ShopCartItemDto shopCartItem : shopCartItems) {
                if (Objects.nonNull(shopCartItem.getComboId()) && shopCartItem.getComboId() != 0) {
                    continue;
                }
                shopCartItem.setIsShareReduce(0);
                // 该商品是否在该优惠券可用
                boolean isCouponsProd = isCouponsProd(shopCartItem.getProdId(), prodIds, shopCoupon.getSuitableProdType());
                if (isCouponsProd) {
                    shopCartItem.setIsShareReduce(1);
                    reduceNum++;
                }
            }
        }
        prodCanUseCouponActualTotal = chooseCouponProdAmount;
        if (chooseCoupon != null) {
            chooseCoupon.setChoose(true);
            // 计算优惠券优惠金额
//            calculateCouponReduce();
            couponReduce = chooseCoupon.getReduceAmount();
            couponInOrderAmount = chooseCoupon.getReduceAmount();
            // 设置分摊优惠金额
            setShareReduce();
        }
        return this;
    }
    /**
     * 判断某个商品是否在此优惠券中
     *
     * @param prodId         在该店铺中的商品商品id
     * @param couponProdIds  优惠券关联的商品id
     * @param couponProdType 优惠券适用商品类型
     * @return 商品是否在此优惠券中
     */
    private boolean isCouponsProd(Long prodId, List<Long> couponProdIds, Integer couponProdType) {
        if (CouponProdType.ALL.value().equals(couponProdType)) {
            return true;
        }
        if (CouponProdType.PROD_IN.value().equals(couponProdType)) {
            if (CollectionUtil.isEmpty(couponProdIds)) {
                return false;
            }
            for (Long couponProdId : couponProdIds) {
                if (Objects.equals(couponProdId, prodId)) {
                    return true;
                }
            }
            return false;
        }
        if (CouponProdType.PROD_NO_IN.value().equals(couponProdType)) {
            if (CollectionUtil.isEmpty(couponProdIds)) {
                return true;
            }
            for (Long couponProdId : couponProdIds) {
                if (Objects.equals(couponProdId, prodId)) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
//    /**
//     * 计算优惠金额
//     */
//    private void calculateCouponReduce() {
//        couponReduce = 0.0;
//        couponInOrderAmount = 0.0;
//        // 代金券
//        if (CouponType.C2M.value().equals(chooseCoupon.getCouponType())) {
//            couponInOrderAmount = chooseCoupon.getReduceAmount();
//        }
//        // 折扣券
//        if (CouponType.C2D.value().equals(chooseCoupon.getCouponType())) {
//            couponInOrderAmount = Arith.roundByBanker(Arith.sub(prodCanUseCouponActualTotal, Arith.div(Arith.mul(prodCanUseCouponActualTotal,
//                    chooseCoupon.getCouponDiscount()), 10)), 2);
//            chooseCoupon.setReduceAmount(couponInOrderAmount);
//        }
//        couponReduce = Arith.add(couponReduce, couponInOrderAmount);
//    }
    /**
     * 设置分摊优惠金额
     */
    private void setShareReduce() {
        double sumReduce = 0.0;
        shopCartItems = shopCartItems.stream().sorted(Comparator.comparing(ProductItemDto::getActualTotal)).collect(Collectors.toList());
        int count = 0;
        for (ShopCartItemDto shopCartItem : shopCartItems) {
            if (Objects.nonNull(shopCartItem.getComboId()) && shopCartItem.getComboId() != 0) {
                continue;
            }
            double shareReduce;
            if (shopCartItem.getIsShareReduce() == 1) {
//                shareReduce = Arith.roundByBanker(Arith.mul(couponInOrderAmount, Arith.div(shopCartItem.getActualTotal(), prodCanUseCouponActualTotal, 10)), 2);
                shareReduce = Arith.div(Arith.mul(shopCartItem.getActualTotal(), couponInOrderAmount),prodCanUseCouponActualTotal, 2);
                count++;
                //如果是最后一项可以参与优惠的商品,直接将剩余的优惠金额赋值给他
                if (count >= reduceNum) {
                    shareReduce = Math.min(Arith.sub(chooseCoupon.getReduceAmount(), sumReduce), shopCartItem.getProductTotalAmount());
                }
                if (Objects.equals(chooseCoupon.getShopId(), 0L)) {
                    // 平台分摊的每一个购物项优惠金额
                    shopCartItem.setPlatformShareReduce(Arith.add(shopCartItem.getPlatformShareReduce(), shareReduce));
                    shopCartItem.setPlatformCouponAmount(shareReduce);
                } else {
                    // 商家分摊的每一个购物项优惠金额
                    shopCartItem.setShareReduce(Arith.add(shopCartItem.getShareReduce(), shareReduce));
                    shopCartItem.setShopCouponAmount(shareReduce);
                }
            } else {
                shareReduce = 0.0;
            }
            // 分摊的优惠金额 不能大于商品金额
            double minShareReduce = Math.min(shareReduce, shopCartItem.getProductTotalAmount());
            shopCartItem.setActualTotal(Arith.sub(shopCartItem.getActualTotal(), minShareReduce));
            // 将对应店铺优惠券优惠的金额放入map中
            if (shopReduceMap.containsKey(shopCartItem.getShopId())) {
                double shopReduce = shopReduceMap.get(shopCartItem.getShopId());
                shopReduceMap.put(shopCartItem.getShopId(), Arith.add(shopReduce, minShareReduce));
            } else {
                shopReduceMap.put(shopCartItem.getShopId(), minShareReduce);
            }
            sumReduce = Arith.add(minShareReduce, sumReduce);
        }
    }
}
yami-shop-coupon/yami-shop-coupon-common/pom.xml
New file
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>yami-shop-coupon</artifactId>
        <groupId>com.yami.shop</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>yami-shop-coupon-common</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-security-common</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
    </dependencies>
</project>
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/constants/CouponStatusEnum.java
New file
@@ -0,0 +1,42 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.constants;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
 * 优惠券状态
 * @author lanhai
 */
@Getter
@AllArgsConstructor
public enum CouponStatusEnum {
    /**   取消投放   */
    CANCEL(-1,"取消投放"),
    /**   自动投放   */
    AUTO_LAUNCH(0, "自动投放"),
    /**   投放       */
    PUT_ON(1, "投放"),
    /**   违规下架   */
    OFFLINE(2, "违规下架"),
    /**   等待审核   */
    WAIT_AUDIT(3, "等待审核"),
    /** 暂不投放*/
    NOT_LAUNCH(4, "暂不投放"),
    ;
    private int value;
    private String desc;
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/constants/UserCouponRecordStatus.java
New file
@@ -0,0 +1,46 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.constants;
/**
 * @author FrozenWatermelon
 * @date 2020/12/28
 */
public enum UserCouponRecordStatus {
    /**
     * 1:冻结
     */
    FREEZE(1),
    /**
     * 使用过
     */
    USED(2),
    /**
     * 3:退回
     */
    REFUND(3)
    ;
    private Integer value;
    public Integer getValue() {
        return value;
    }
    public void setValue(Integer value) {
        this.value = value;
    }
    UserCouponRecordStatus(Integer value) {
        this.value = value;
    }
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/constants/UserCouponStatus.java
New file
@@ -0,0 +1,46 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.constants;
/**
 * @author FrozenWatermelon
 * @date 2020/12/28
 */
public enum UserCouponStatus {
    /**
     * 0:失效
     */
    INVALID(0),
    /**
     * 1:有效
     */
    EFFECTIVE(1),
    /**
     * 使用过
     */
    USED(2)
    ;
    private Integer value;
    public Integer getValue() {
        return value;
    }
    public void setValue(Integer value) {
        this.value = value;
    }
    UserCouponStatus(Integer value) {
        this.value = value;
    }
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/constants/ValidTimeTypeEnum.java
New file
@@ -0,0 +1,35 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.constants;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
 * 优惠券状态
 * @author lhd
 */
@Getter
@AllArgsConstructor
public enum ValidTimeTypeEnum {
    /**   固定时间       */
    FIXED(1, "固定时间"),
    /**   领取后生效   */
    RECEIVE(2, "领取后生效")
    ;
    private int value;
    private String desc;
    public Integer value() {
        return value;
    }
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/dao/CouponMapper.java
New file
@@ -0,0 +1,223 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.app.dto.CouponDto;
import com.yami.shop.bean.app.dto.CouponOrderDto;
import com.yami.shop.common.util.PageAdapter;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.coupon.common.model.Coupon;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
 * 优惠券
 *
 * @author lanhai
 */
public interface CouponMapper extends BaseMapper<Coupon> {
    /**
     * 根据优惠券id获取优惠券的信息及可用商品信息
     *
     * @param id 优惠券id
     * @return 优惠券的信息及可用商品信息
     */
    Coupon getCouponAndCouponProdsByCouponId(@Param("id") Long id);
    /**
     * 修改优惠券库存
     *
     * @param couponId 优惠券id
     * @return 结果
     */
    int updateCouponStocksAndVersion(@Param("couponId") Long couponId);
    /**
     * 设置店铺的过期优惠券为过期状态
     *
     * @param now 时间
     */
    void updateOverdueStatusByTime(@Param("now") Date now);
    /**
     * 投放优惠券
     *
     * @param now 时间
     */
    void putonCoupon(@Param("now") Date now);
    /**
     * 获取通用优惠券列表
     *
     * @param userId 用户id
     * @return 通用优惠券列表
     */
    List<CouponDto> generalCouponList(@Param("userId") String userId);
    /**
     * 通过优惠券状态获取优惠券列表
     *
     * @param page   分页
     * @param userId 用户id
     * @param status 状态
     * @return 优惠券分页列表
     */
    IPage<CouponDto> getCouponListByStatus(IPage<CouponDto> page, @Param("userId") String userId, @Param("status") Integer status);
    /**
     * 通过店铺id及用户id获取用户未使用的优惠券
     *
     * @param userId 用户id
     * @param shopId 店铺id
     * @return 用户未使用的优惠券列表
     */
    List<CouponOrderDto> getCouponListByShopIds(@Param("userId") String userId, @Param("shopId") Long shopId);
    /**
     * 查询需要更新的店铺id列表
     *
     * @param now 当前时间
     * @return 店铺id列表
     */
    List<Long> listOverdueStatusShopIds(@Param("now") Date now);
    /**
     * 获取某店铺所有的投放优惠券和优惠商品列表
     *
     * @param shopId 店铺id
     * @return 优惠券列表
     */
    List<Coupon> listPutonCouponAndCouponProdsByShopId(@Param("shopId") Long shopId);
    /**
     * 获取用户的优惠券信息
     *
     * @param userId 用户id
     * @return 优惠券列表
     */
    List<CouponDto> listCouponIdsByUserId(@Param("userId") String userId);
    /**
     * 获取用户各个状态下的优惠券个数
     *
     * @param userId 用户id
     * @return 用户各个状态下的优惠券个数
     */
    Map<String, Long> getCouponCountByStatus(@Param("userId") String userId);
    /**
     * 平台  -- 分页获取优惠券数据
     *
     * @param page   分页
     * @param coupon 优惠券
     * @return 分页优惠券数据
     */
    IPage<Coupon> getPlatformPage(@Param("page") PageParam<Coupon> page, @Param("coupon") Coupon coupon);
    /**
     * 商家端--分页获取优惠券数据
     *
     * @param page   分页参数
     * @param coupon 优惠券
     * @return 优惠券数据
     */
    IPage<Coupon> getMultiShopPage(@Param("page") PageParam<Coupon> page, @Param("coupon") Coupon coupon);
    /**
     * 根据优惠券id获取其领取次数
     *
     * @param couponId 优惠券id
     * @param shopId   店铺id
     * @return 领取次数
     */
    Integer countTakeNum(@Param("couponId") Long couponId, @Param("shopId") Long shopId);
    /**
     * 根据优惠券id获取其使用次数
     *
     * @param couponId 优惠券id
     * @return 使用次数
     */
    Integer countUseNum(@Param("couponId") Long couponId);
    /**
     * 更新投放状态
     *
     * @param couponId 优惠券id
     * @param status   更新的状态
     * @return 结果
     */
    int updatePutOnStatusByCouponId(@Param("couponId") Long couponId, @Param("status") int status);
    /**
     * 更新投放状态
     *
     * @param couponId      优惠券id
     * @param overdueStatus 投放状态
     * @return 结果
     */
    int updateOverdueStatusByCouponId(@Param("couponId") Long couponId, @Param("overdueStatus") int overdueStatus);
    /**
     * 根据优惠券适用类型,获取优惠券列表
     *
     * @param couponIds 用户id
     * @param lang      语言
     * @return 优惠券列表
     */
    List<CouponDto> getCouponList(@Param("couponIds") List<Long> couponIds, @Param("lang") Integer lang);
    /**
     * 根据优惠券适用类型,获取优惠券列表
     *
     * @param couponForAllProd  适用于所有商品列表
     * @param couponForProd     适用于部分商品列表
     * @param couponForElseProd 不适用于那些商品列表
     * @return 优惠券列表
     */
    List<CouponDto> getCouponListTourist(@Param("couponForAllProd") List<CouponDto> couponForAllProd, @Param("couponForProd") List<Long> couponForProd,
                                         @Param("couponForElseProd") List<CouponDto> couponForElseProd);
    /**
     * 获取店铺可领取优惠券id列表
     *
     * @param pageAdapter 分页信息
     * @return 优惠券列表
     */
    List<Long> getShopAvailableCouponIds(@Param("adapter") PageAdapter pageAdapter);
    /**
     * 获取优惠券数量
     *
     * @return 优惠券数量
     */
    long countCouponPageByCouponDto();
    /**
     * 游客状态查询通用优惠券列表
     *
     * @return 通用优惠券列表
     */
    List<CouponDto> generalCouponListTourist();
    /**
     * 更新优惠券
     * @param coupon
     */
    void updateCoupon(@Param("coupon") Coupon coupon);
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/dao/CouponProdMapper.java
New file
@@ -0,0 +1,41 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yami.shop.coupon.common.model.CouponProd;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * 优惠券商品信息
 * @author lanhai
 */
public interface CouponProdMapper extends BaseMapper<CouponProd> {
    /**
     * 删除优惠券关联
     * @param couponId 优惠券id
     */
    void deleteCouponProdsByCouponId(@Param("couponId") Long couponId);
    /**
     * 新增优惠券关联
     * @param couponId 优惠券id
     * @param prodIds 商品ids
     */
    void insertCouponProdsBatch(@Param("couponId") Long couponId, @Param("prodIds") List<Long> prodIds);
    /**
     * 根据优惠券ids删除优惠券关联
     * @param couponIds 优惠券ids
     */
    void deleteCouponProdsByCouponIds(List<String> couponIds);
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/dao/CouponUseRecordMapper.java
New file
@@ -0,0 +1,80 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yami.shop.coupon.common.model.CouponUseRecord;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * 优惠券使用记录
 *
 * @author yami code generator
 * @date 2019-05-15 09:04:57
 */
public interface CouponUseRecordMapper extends BaseMapper<CouponUseRecord> {
    /**
     * 批量插入用户优惠券使用记录
     *
     * @param couponUseRecordsList 用户优惠券使用记录集合
     */
    void addCouponUseRecode(@Param("couponUseRecordsList") List<CouponUseRecord> couponUseRecordsList);
    /**
     * 批量更新商家券、平台券
     *
     * @param status          状态
     * @param orderNumberList 订单编号list
     */
    void batchUpdateRecordByStatusAndOrderNums(@Param("status") int status, @Param("orderNumberList") List<String> orderNumberList);
    /**
     * 获取订单中使用的优惠券
     *
     * @param orderNumber 订单编号
     * @return
     */
    List<CouponUseRecord> listByOrderNumber(@Param("orderNumber") String orderNumber);
    /**
     * 获取全部订单号字符串
     * @param orderNumber
     * @return
     */
    List<CouponUseRecord> getOrderNumberContact(@Param("orderNumber") String orderNumber);
    /**
     * 根据id, 批量更新商家券、平台券
     *
     * @param status
     * @param ids
     */
    void batchUpdateRecordStatusByStatusAndIds(@Param("status") int status, @Param("ids") List<Long> ids);
    /**
     * 获取需要解锁的、用户所领取的优惠券
     *
     * @param orderNumber 订单id
     * @return 用户所领取的优惠券id
     */
    List<Long> listCouponUserIdsByOrderNumber(@Param("orderNumber") String orderNumber);
    /**
     * 将锁定状态标记为已解锁
     *
     * @param couponUserIds 用户所领取的优惠券id
     * @return
     */
    int unLockByIds(@Param("couponUserIds") List<Long> couponUserIds);
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/dao/CouponUserMapper.java
New file
@@ -0,0 +1,195 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yami.shop.bean.param.*;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.coupon.common.model.CouponUser;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
/**
 * 优惠券商品信息
 *
 * @author lanhai
 */
public interface CouponUserMapper extends BaseMapper<CouponUser> {
    /**
     * 获取用户优惠券信息
     *
     * @param userId 用户id
     * @return 用户优惠券信息
     */
    List<CouponUser> getCouponAndCouponUserByUserId(@Param("userId") String userId);
    /**
     * 通过关联ids获取用户优惠券信息
     *
     * @param couponUserIds 用户优惠券ids
     * @return 用户优惠券信息
     */
    List<CouponUser> getCouponAndCouponUserByCouponUserIds(@Param("couponUserIds") List<Long> couponUserIds);
    /**
     * 删除用户失效半年以上的优惠券
     *
     * @param date 时间
     */
    void deleteUnValidTimeCoupons(@Param("date") Date date);
    /**
     * 设置用户的过期优惠券为失效状态
     *
     * @param now 时间
     */
    void updateStatusByTime(@Param("now") Date now);
    /**
     * 删除用户优惠关联信息
     *
     * @param userId   用户id
     * @param couponId 优惠券id
     */
    void deleteUserCoupon(@Param("userId") String userId, @Param("couponId") Long couponId);
    /**
     * 修改用户优惠券状态
     *
     * @param status       状态
     * @param couponUserId 优惠券用户id
     */
    void updateUseStatusByCouponUserId(@Param("status") Integer status, @Param("couponUserId") Long couponUserId);
    /**
     * 批量修改用户优惠券状态
     *
     * @param status        状态
     * @param couponUserIds 优惠券用户ids
     */
    void batchUpdateUserCouponStatus(@Param("status") int status, @Param("couponUserIds") List<Long> couponUserIds);
    /**
     * 批量修改用户优惠券状态通过订单编号
     *
     * @param status      状态
     * @param orderNumber 订单编号
     */
    void updateStatusByOrderNumber(@Param("status") int status, @Param("orderNumber") String orderNumber);
    /**
     * 根据日期判断用户优惠券详情
     *
     * @param page
     * @param param 日期
     * @return 优惠券详情
     */
    Page<CouponAnalysisParam> getCouponAnalysisParamByDate(Page page, @Param("param") ProdEffectParam param);
    /**
     * 根据日期获取优惠券使用次数
     *
     * @param couponId 优惠券id
     * @param param
     * @return 使用次数
     */
    Integer countUseNum(@Param("couponId") Long couponId, @Param("param") ProdEffectParam param);
    /**
     * 获取用户优惠券领取次数
     *
     * @param couponId 优惠券id
     * @param status   状态
     * @param param    参数
     * @return 领取次数
     */
    Integer countTakeNum(@Param("couponId") Long couponId, @Param("status") Integer status, @Param("param") ProdEffectParam param);
    /**
     * 领券会员数
     *
     * @param param 相关条件参数
     * @return 领券会员数
     */
    Integer countMemberGetCoupon(@Param("param") CustomerReqParam param);
    /**
     * 领券会员数
     *
     * @param param 会员类型参数
     * @return 领券会员数
     */
    Integer countMemberCouponByParam(@Param("param") MemberReqParam param);
    /**
     * 用户未使用的并且是未过期的优惠券数量
     *
     * @param userId 用户id
     * @param date   时间
     * @return 优惠券数量
     */
    Integer countCouponUsableNums(@Param("userId") String userId, @Param("date") Date date);
    /**
     * 用户已使用的优惠券数量
     *
     * @param userId 用户id
     * @return 优惠券数量
     */
    Integer countCouponUsedNums(@Param("userId") String userId);
    /**
     * 用户已失效的优惠券
     *
     * @param userId 用户id
     * @return 优惠券数量
     */
    Integer countCouponExpiredNums(@Param("userId") String userId);
    /**
     * 获取某个用户的优惠券明细
     *
     * @param page   分页信息
     * @param userId 用户id
     * @param status 状态
     * @return 分页优惠券明细
     */
    IPage<CouponUser> getPageByUserId(PageParam<CouponUser> page, @Param("userId") String userId, @Param("status") Integer status);
    /**
     * 根据id获取用户正常优惠券的数量
     *
     * @param couponUserIds 选择的优惠券
     * @param userId        用户id
     * @return 用户正常优惠券的数量
     */
    int countNormalByCouponUserId(@Param("couponUserIds") List<Long> couponUserIds, @Param("userId") String userId);
    /**
     * 获取用户领取的优惠券及数量
     * @param couponIds
     * @param userId
     * @return
     */
    List<CouponUser> listByCouponIdsAndUserId(@Param("couponIds") List<Long> couponIds, @Param("userId") String userId);
    /**
     * 商家端获取优惠券各种状态和数量
     * @param userId
     * @param shopId
     * @return
     */
    CouponUserParam getCouponCountInfo(@Param("userId") String userId, @Param("shopId") Long shopId);
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/dto/CouponRecordDTO.java
New file
@@ -0,0 +1,40 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.dto;
import lombok.Data;
/**
 * @author FrozenWatermelon
 * @date 2020/12/23
 */
@Data
public class CouponRecordDTO {
    /**
     * 订单id
     */
    private String orderNumbers;
    /**
     * 优惠券id
     */
    private Long couponId;
    /**
     * 用户优惠券id
     */
    private Long couponUserId;
    /**
     * 优惠金额
     */
    private Double reduceAmount;
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/listener/CancelOrderListener.java
New file
@@ -0,0 +1,43 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.listener;
import com.yami.shop.bean.event.CancelOrderEvent;
import com.yami.shop.bean.order.CancelOrderOrder;
import com.yami.shop.coupon.common.service.CouponUseRecordService;
import com.yami.shop.coupon.common.service.CouponUserService;
import lombok.AllArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
 * 取消订单事件
 * @author lanhai
 */
@Component("couponCancelOrderListener")
@AllArgsConstructor
public class CancelOrderListener {
//    final private CouponUseRecordService couponUseRecordService;
    final private CouponUserService couponUserService;
    @EventListener(CancelOrderEvent.class)
    @Order(CancelOrderOrder.COUPON)
    public void couponCancelOrderEvent(CancelOrderEvent event) {
        // 将优惠券状态改为可用状态并删除优惠券记录
        String userId = event.getOrder().getUserId();
        String orderNumber = event.getOrder().getOrderNumber();
        couponUserService.cancelOrder(userId, orderNumber);
//        couponUseRecordService.unlockCoupon(event.getOrder());
    }
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/listener/OrderRefundListener.java
New file
@@ -0,0 +1,117 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.listener;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.dto.OrderRefundDto;
import com.yami.shop.bean.enums.RefundStatusEnum;
import com.yami.shop.bean.event.OrderRefundSuccessEvent;
import com.yami.shop.bean.model.Order;
import com.yami.shop.coupon.common.dao.CouponUseRecordMapper;
import com.yami.shop.coupon.common.model.CouponUseRecord;
import com.yami.shop.coupon.common.model.CouponUser;
import com.yami.shop.coupon.common.service.CouponUserService;
import com.yami.shop.service.OrderService;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import java.util.*;
/**
 * 退款订单监听
 * @author lhd
 */
@Component("couponOrderRefundListener")
@AllArgsConstructor
public class OrderRefundListener {
    private final OrderService orderService;
    private final CouponUseRecordMapper couponUseRecordMapper;
    private final CouponUserService couponUserService;
    /**
     * 退还用户此笔退款订单使用的优惠券
     */
    @EventListener(OrderRefundSuccessEvent.class)
    public void conponOrderRefundSuccessEvent(OrderRefundSuccessEvent event) {
        OrderRefundDto orderRefundDto = event.getOrderRefundDto();
        //获取退款的所有订单项
        if (CollectionUtils.isEmpty(orderRefundDto.getOrderItems())) {
            return;
        }
        Order order = orderService.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNumber, orderRefundDto.getOrderNumber()));
        // 不是整单退款,不需要退优惠券
        if (!Objects.equals(order.getRefundStatus(), RefundStatusEnum.SUCCEED.value())) {
            return;
        }
        String orderNumber = order.getOrderNumber();
        List<CouponUseRecord> records = couponUseRecordMapper.getOrderNumberContact(orderNumber);
        List<CouponUseRecord> list = handlerCouponRecords(records, orderNumber);
        // 订单没有使用优惠券,不需要处理
        if (CollUtil.isEmpty(list)) {
            return;
        }
        long currentTime = System.currentTimeMillis();
        List<CouponUser> couponUsers = new ArrayList<>();
        List<Long> ids = new ArrayList<>();
        for (CouponUseRecord couponUseRecord : list) {
            CouponUser couponUser = couponUseRecord.getCouponUser();
            // 已过有效时间、违规下架或已过期的优惠券, 不退还
            boolean notHandle = currentTime >= couponUser.getUserEndTime().getTime() || couponUser.getCoupon().getPutonStatus() > 1 || Objects.equals(couponUser.getCoupon().getOverdueStatus(), 0);
            if (notHandle) {
                continue;
            }
            couponUseRecord.setStatus(3);
            ids.add(couponUseRecord.getCouponUseRecordId());
            couponUseRecord.getCouponUser().setStatus(1);
            couponUsers.add(couponUseRecord.getCouponUser());
        }
        couponUseRecordMapper.batchUpdateRecordStatusByStatusAndIds(3, ids);
        couponUserService.updateBatchById(couponUsers);
    }
    private List<CouponUseRecord> handlerCouponRecords(List<CouponUseRecord> records, String orderNumber) {
        if (CollUtil.isEmpty(records)) {
            return new ArrayList<>();
        }
        Set<CouponUseRecord> resList = new HashSet<>();
        for (CouponUseRecord record : records) {
            String dbOrderNumber = record.getOrderNumber();
            String[] orderNums = dbOrderNumber.split(",");
            //查看除当前订单号之外的其他订单是否已经退款完成
            boolean flag = true;
            if (orderNums.length > 1) {
                for (String orderNum : orderNums) {
                    if (!orderNum.equals(orderNumber)) {
                        Order order = orderService.getOrderByOrderNumber(orderNum);
                        boolean isRefundSuccess = Objects.nonNull(order.getRefundStatus()) && Objects.equals(order.getRefundStatus(),2);
                        if (!isRefundSuccess) {
                            flag = false;
                        }
                    }
                }
            }
            List<CouponUseRecord> couponUseRecords;
            if (flag) {
                // 单个或多个订单均退款成功
                couponUseRecords = couponUseRecordMapper.listByOrderNumber(dbOrderNumber);
            } else {
                //有订单没有退款完成就只查当前订单自己的优惠券记录
                couponUseRecords = couponUseRecordMapper.listByOrderNumber(orderNumber);
            }
            resList.addAll(couponUseRecords);
        }
        return new ArrayList<>(resList);
    }
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/listener/PaySuccessOrderListener.java
New file
@@ -0,0 +1,69 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.listener;
import com.google.common.collect.Lists;
import com.yami.shop.bean.event.BatchBindCouponEvent;
import com.yami.shop.bean.event.PaySuccessOrderEvent;
import com.yami.shop.bean.order.PaySuccessOrderOrder;
import com.yami.shop.common.config.Constant;
import com.yami.shop.coupon.common.constants.UserCouponRecordStatus;
import com.yami.shop.coupon.common.service.CouponService;
import com.yami.shop.coupon.common.service.CouponUseRecordService;
import com.yami.shop.coupon.common.service.CouponUserService;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Objects;
/**
 * 优惠券
 * @author lanhai
 */
@Component("couponPaySuccessListener")
@AllArgsConstructor
public class PaySuccessOrderListener {
    private final CouponUseRecordService couponUseRecordService;
    private final CouponService couponService;
    private final CouponUserService couponUserService;
    /**
     * 更新优惠券使用记录状态
     */
    @EventListener(PaySuccessOrderEvent.class)
    @Order(PaySuccessOrderOrder.COUPON)
    public void couponPaySuccessListener(PaySuccessOrderEvent event) {
        if(Objects.equals(event.getOrders().get(0).getShopId(),Constant.PLATFORM_SHOP_ID)){
            return;
        }
        List<String> orderNumberList = Lists.newArrayList();
        List<com.yami.shop.bean.model.Order> orders = event.getOrders();
        for (com.yami.shop.bean.model.Order order : orders) {
            orderNumberList.add(order.getOrderNumber());
        }
        if (CollectionUtils.isNotEmpty(orderNumberList)) {
            couponUseRecordService.batchUpdateRecordByStatusAndOrderNums(UserCouponRecordStatus.USED.getValue(), orderNumberList);
        }
    }
    /**
     * 批量绑定优惠券,如果已达上限等领取不了的情况直接退出。
     */
    @EventListener(BatchBindCouponEvent.class)
    public void batchBindCouponEventListener(BatchBindCouponEvent event) {
        couponService.batchBindCouponByIds(event.getCouponIds(),event.getUserId(),event.getShopId());
    }
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/model/Coupon.java
New file
@@ -0,0 +1,124 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
 * 优惠券
 * @author lanhai
 */
@Data
@TableName("tz_coupon")
@Schema(description = "优惠券")
public class Coupon implements Serializable {
    private static final long serialVersionUID = 8018312153820119913L;
    @TableId
    @Schema(description = "优惠券id" )
    private Long couponId;
    @Schema(description = "店铺ID" )
    private Long shopId;
    @Schema(description = "优惠券名称" )
    private String couponName;
    @Schema(description = "副标题" )
    private String subTitle;
    @Schema(description = "优惠类型 1:代金券 2:折扣券 3:兑换券" )
    private Integer couponType;
    @Schema(description = "使用条件" )
    private Double cashCondition;
    @Schema(description = "减免金额" )
    private Double reduceAmount;
    @Schema(description = "折扣额度" )
    private Double couponDiscount;
    @Schema(description = "生效类型 1:固定时间 2:领取后生效" )
    private Integer validTimeType;
    @Schema(description = "投放时间" )
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date launchTime;
    @Schema(description = "开始时间" )
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date startTime;
    @Schema(description = "结束时间" )
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date endTime;
    @Schema(description = "领券后X天起生效" )
    private Integer afterReceiveDays;
    @Schema(description = "有效天数" )
    private Integer validDays;
    @Schema(description = "库存" )
    private Integer stocks;
    @Schema(description = "原始库存" )
    private Integer sourceStock;
    @Schema(description = "适用商品类型 0全部商品参与 1指定商品参与 2指定商品不参与" )
    private Integer suitableProdType;
    @Schema(description = "每个用户领券上限,如不填则默认为1" )
    private Integer limitNum;
    @Schema(description = "版本号" )
    private Integer version;
    @Schema(description = "是否积分优惠券 0不是 1是" )
    private Integer isScoreType;
    @Schema(description = "积分价格" )
    private Integer scorePrice;
    @Schema(description = "优惠券过期状态 0:过期 1:未过期" )
    private Integer overdueStatus;
    @Schema(description = "优惠券投放状态 0:未投放 1:投放 -1取消投放" )
    private Integer putonStatus;
    @Schema(description = "优惠商品" )
    @TableField(exist = false)
    private List<CouponProd> couponProds;
    @Schema(description = "优惠券所在的店铺" )
    @TableField(exist = false)
    private String shopName;
    @Schema(description = "获取方式  0=客户领取 1=平台发放" )
    private Integer getWay = 0;
    @Schema(description = "优惠券领取次数" )
    @TableField(exist = false)
    private Integer takeNum = 0;
    @Schema(description = "优惠券微商城使用次数" )
    @TableField(exist = false)
    private Integer useNum = 0;
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/model/CouponProd.java
New file
@@ -0,0 +1,48 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.yami.shop.common.serializer.json.ImgJsonSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
/**
 * 优惠券商品信息
 * @author lanhai
 */
@Data
@TableName("tz_coupon_prod")
public class CouponProd implements Serializable {
    @TableId
    @Schema(description = "优惠券商品ID" )
    private Long couponProdId;
    @Schema(description = "优惠券ID" )
    private Long couponId;
    @Schema(description = "商品ID" )
    private Long prodId;
    @Schema(description = "商品名称" )
    @TableField(exist=false)
    private String prodName;
    @Schema(description = "商品主图" )
    @TableField(exist=false)
    @JsonSerialize(using = ImgJsonSerializer.class)
    private String pic;
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/model/CouponUseRecord.java
New file
@@ -0,0 +1,74 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
 * 优惠券使用记录
 *
 * @author yami code generator
 * @date 2019-05-15 09:04:57
 */
@Data
@TableName("tz_coupon_use_record")
public class CouponUseRecord implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 优惠券使用id
     */
    @TableId
    private Long couponUseRecordId;
    @Schema(description = "创建时间" )
    private Date createTime;
    @Schema(description = "更新时间" )
    private Date updateTime;
    /**
     * 用户优惠券id
     */
    private Long couponUserId;
    /**
     * 用户id
     */
    private String userId;
    /**
     * 订单编码
     */
    private String orderNumber;
    /**
     * 金额
     */
    private Double amount;
    /**
     * 使用时间
     */
    private Date useTime;
    /**
     * 使用状态(1:冻结 2:已使用 3:已退还)
     */
    private Integer status;
    /**
     * 用户领取优惠券
     */
    @TableField(exist = false)
    private CouponUser couponUser;
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/model/CouponUser.java
New file
@@ -0,0 +1,90 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
 * 优惠券商品信息
 * @author lanhai
 */
@Data
@TableName("tz_coupon_user")
public class CouponUser implements Serializable {
    private static final long serialVersionUID = 129965893236674626L;
    /**
     * 优惠券用户ID
     */
    @TableId
    private Long couponUserId;
    /**
     * 优惠券ID
     */
    private Long couponId;
    /**
     * 用户ID
     */
    private String userId;
    /**
     * 领券时间
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date receiveTime;
    /**
     * 优惠券状态 0:失效 1:有效 2:使用过
     */
    private Integer status;
    /**
     * 开始时间
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date userStartTime;
    /**
     * 结束时间
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date userEndTime;
    /**
     * 是否删除
     */
    private Integer isDelete;
    /**
     * 优惠券
     */
    @TableField(exist = false)
    private Coupon coupon;
    /**
     * 优惠券使用记录id
     */
    @TableField(exist = false)
    private Long couponUseRecordId;
    /**
     * 用户领取的优惠券数量
     */
    @TableField(exist = false)
    private Integer curUserReceiveCount;
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/param/UserCouponParam.java
New file
@@ -0,0 +1,21 @@
package com.yami.shop.coupon.common.param;
import com.yami.shop.bean.param.SendUserCouponsParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
 * 批量发放优惠券给会员
 * @author TRACK
 */
@Data
public class UserCouponParam {
    @Schema(description = "用户id列表")
    private List<String> userIds;
    @Schema(description = "发放优惠券列表")
    private List<SendUserCouponsParam> coupons;
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/CouponProdService.java
New file
@@ -0,0 +1,21 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yami.shop.coupon.common.model.CouponProd;
/**
 *
 * @author lgh on 2018/12/27.
 */
public interface CouponProdService extends IService<CouponProd> {
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/CouponService.java
New file
@@ -0,0 +1,234 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yami.shop.bean.app.dto.CouponDto;
import com.yami.shop.bean.app.dto.CouponOrderDto;
import com.yami.shop.bean.app.dto.ProductDto;
import com.yami.shop.bean.param.OfflineHandleEventAuditParam;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.coupon.common.model.Coupon;
import com.yami.shop.coupon.common.model.CouponUser;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
 * @author lgh on 2018/12/27.
 */
public interface CouponService extends IService<Coupon> {
    /**
     * 修改优惠券关联商品信息
     * @param coupon 优惠券信息
     */
    void updateCouponAndCouponProds(@Valid Coupon coupon);
    /**
     * 插入优惠券关联商品信息
     * @param coupon 优惠券信息
     */
    void insertCouponAndCouponProds(@Valid Coupon coupon);
    /**
     * 获取优惠券关联商品信息
     * @param id 优惠券id
     * @return
     */
    Coupon getCouponAndCouponProdsByCouponId(Long id);
    /**
     * 根据用户id发放优惠券
     * @param coupon 优惠券信息
     * @param userId 用户id
     */
    void receive(Coupon coupon, String userId);
    /**
     * 定时任务,改变店铺优惠券的状态
     *
     * @param now 时间
     */
    void changeCoupon(Date now);
    /**
     * 投放优惠券
     * @param now 时间
     */
    void putonCoupon(Date now);
    /**
     * 删除优惠券
     * @param couponId 优惠券id
     */
    void deleteByCouponId(Long couponId);
    /**
     * 获取通用券列表
     * @param userId 用户id
     * @return 通用券列表
     */
    List<CouponDto> generalCouponList(String userId);
    /**
     * 游客状态查询所有通用优惠券列表
     * @return 通用优惠券列表
     */
    List<CouponDto> generalCouponList();
    /**
     * 通过状态查看用户的优惠券列表信息
     * @param page 分页信息
     * @param userId 用户id
     * @param status 状态
     * @return 用户的优惠券列表信息
     */
    IPage<CouponDto> getCouponListByStatus(IPage<CouponDto> page, String userId, Integer status);
    /**
     * 通过优惠券id删除用户优惠券
     * @param userId 用户id
     * @param couponId 优惠券id
     */
    void deleteUserCouponByCouponId(String userId, Long couponId);
    /**
     * 获取用户有效的优惠券
     * @param userId 用户id
     * @param shopId 店铺id
     * @return 用户有效的优惠券列表
     */
    List<CouponOrderDto> getCouponListByShopIds(String userId, Long shopId);
    /**
     * 获取已投放优惠券
     *
     * @param shopId 店铺id
     * @return 已投放优惠券
     */
    List<Coupon> listPutonByShopId(Long shopId);
    /**
     * 查看用户拥有的所有优惠券
     * @param userId 用户id
     * @return 用户拥有的所有优惠券
     */
    List<CouponDto> listCouponIdsByUserId(String userId);
    /**
     * 通过优惠券id获取商品列表
     * @param page 分页信息
     * @param coupon 优惠券信息
     * @param dbLang 语言
     * @return 商品列表
     */
    IPage<ProductDto> prodListByCoupon(PageParam<ProductDto> page, Coupon coupon, Integer dbLang);
    /**
     * 商家端分页获取优惠券数据
     * @param page 分页参数
     * @param coupon 优惠券
     * @return 优惠券数据
     */
    IPage<Coupon> getMultiShopPage(PageParam<Coupon> page, Coupon coupon);
    /**
     * 获取各个状态下优惠券个数
     *
     * @param userId 用户id
     * @return 各个状态下优惠券个数map
     */
    Map<String, Long> getCouponCountByStatus(String userId);
    /**
     *  平台  --获取分页优惠券数据
     * @param page 分页信息
     * @param coupon 优惠券信息
     * @return 分页优惠券数据
     */
    IPage<Coupon> getPlatformPage(PageParam<Coupon> page, Coupon coupon);
    /**
     * 平台 --下线活动
     * @param coupon 优惠券信息
     * @param offlineReason 下线备注
     * @param sysUserId 系统用户id
     */
    void offline(Coupon coupon, String offlineReason, Long sysUserId);
    /**
     * 平台 --审核活动
     * @param offlineHandleEventAuditParam 审核信息
     * @param sysUserId 系统用户id
     */
    void auditCoupon(OfflineHandleEventAuditParam offlineHandleEventAuditParam, Long sysUserId);
    /**
     * 申请活动审核
     * @param eventId 事件id
     * @param couponId 优惠券id
     * @param reapplyReason 申请理由
     */
    void auditApply(Long eventId, Long couponId, String reapplyReason);
    /**
     *  移除优惠券缓存
     *
     * @param shopId 店铺id
     */
    void removeCouponAndCouponProdsCache(Long shopId);
    /**
     * 批量绑定优惠券,如果已达上限等领取不了的情况直接退出
     * @param couponIds 优惠券ids
     * @param userId 用户id
     * @param shopId 店铺id
     */
    void batchBindCouponByIds(List<Long> couponIds, String userId,Long shopId);
    /**
     * 对用户发放优惠券,如果已达上限等领取不了的情况直接退出
     * @param couponId 优惠券id
     * @param userId 用户id
     * @param couponNums 优惠券数量
     * @param shopId 店铺id
     */
    void bindCouponById(Long couponId, String userId, Integer couponNums, Long shopId);
    /**
     * 获取  领优惠卷 接口的优惠券列表
     * @param page 分页信息
     * @param userId 用户id
     * @return 优惠券列表
     */
    IPage<CouponDto> getCouponList(Page<CouponDto> page, String userId);
    /**
     * 获取所有可领取的优惠券
     * @param page 分页信息
     * @return 可领取的优惠券
     */
    IPage<CouponDto> getCouponList(Page<CouponDto> page);
    /**
     * 获取某个用户的优惠券明细
     * @param page 分页
     * @param userId 用户id
     * @param status 状态
     * @return 优惠券明细
     */
    IPage<CouponUser> getPageByUserId(PageParam<CouponUser> page, String userId, Integer status);
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/CouponUseRecordService.java
New file
@@ -0,0 +1,54 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yami.shop.bean.model.Order;
import com.yami.shop.coupon.common.dto.CouponRecordDTO;
import com.yami.shop.coupon.common.model.CouponUseRecord;
import java.util.List;
/**
 * 优惠券使用记录
 *
 * @author yami code generator
 * @date 2019-05-15 09:04:57
 */
public interface CouponUseRecordService extends IService<CouponUseRecord> {
    /**
     * 添加优惠券使用记录
     *
     * @param couponUseList
     */
    void addCouponUseRecode(List<CouponUseRecord> couponUseList);
    /**
     * 通过订单列表和批量修改记录状态
     * @param status 状态
     * @param orderNumberList 订单编号列表
     */
    void batchUpdateRecordByStatusAndOrderNums(int status, List<String> orderNumberList);
    /**
     * 锁定订优惠券状态
     * @param lockCouponParams 订单id和优惠券id关联信息
     * @return void
     */
    void lockCoupon(List<CouponRecordDTO> lockCouponParams, String userId);
    /**
     * 根据订单号进行优惠券解锁
     * @param order 订单信息
     */
    void unlockCoupon(Order order);
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/CouponUserService.java
New file
@@ -0,0 +1,89 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yami.shop.bean.param.*;
import com.yami.shop.coupon.common.model.CouponUser;
import java.util.Date;
import java.util.List;
/**
 * @author lgh on 2018/12/27.
 */
public interface CouponUserService extends IService<CouponUser> {
//    List<CouponUser> getCouponAndCouponUserByCouponUserIds(List<Long> couponUserIds);
    /**
     * 删除用户失效半年以上的优惠券
     * @param date 时间
     */
    void deleteUnValidTimeCoupons(Date date);
    /**
     * 设置用户的过期优惠券为失效状态
     * @param now 时间
     */
    void updateStatusByTime(Date now);
    /**
     * 将优惠券状态改为可用状态并删除优惠券记录
     * @param userId 用户id
     * @param orderNumber 订单编号
     */
    void cancelOrder(String userId, String orderNumber);
    /**
     * 卡券分析,卡券昨日关键指标
     * @param param 参数信息
     * @return 卡券昨日关键指标
     */
    List<CouponAnalysisParam> getCouponAnalysis(ProdEffectParam param);
    /**
     * 领券会员数
     * @param param 参数信息
     * @return 领券会员数
     */
    Integer countMemberGetCoupon(CustomerReqParam param);
    /**
     * 领券会员数
     * @param param 参数信息
     * @return 领券会员数
     */
    Integer countMemberCouponByParam(MemberReqParam param);
    /**
     * 获取优惠券各种状态的数量
     * @param userId 用户id
     * @return 用户优惠券信息
     */
    CouponUserParam getCouponCountByUserId(String userId);
    /**
     * 根据日期获得优惠券详情信息
     * @param page page参数
     * @param param 日期参数
     * @return 优惠券详情信息
     */
    Page<CouponAnalysisParam> getCouponAnalysisParamByDate(Page page,ProdEffectParam param);
    /**
     * 商家端获取优惠券各种状态数量
     * @param userId
     * @param shopId
     * @return
     */
    CouponUserParam getCouponCountInfo(String userId, Long shopId);
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/impl/CouponProdServiceImpl.java
New file
@@ -0,0 +1,29 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.coupon.common.dao.CouponProdMapper;
import com.yami.shop.coupon.common.model.CouponProd;
import com.yami.shop.coupon.common.service.CouponProdService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 *
 * @author lgh on 2018/12/27.
 */
@Service
public class CouponProdServiceImpl extends ServiceImpl<CouponProdMapper, CouponProd> implements CouponProdService {
    @Autowired
    private CouponProdMapper couponProdMapper;
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/impl/CouponServiceImpl.java
New file
@@ -0,0 +1,582 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.app.dto.CouponDto;
import com.yami.shop.bean.app.dto.CouponOrderDto;
import com.yami.shop.bean.app.dto.ProductDto;
import com.yami.shop.bean.enums.CouponProdType;
import com.yami.shop.bean.enums.CouponType;
import com.yami.shop.bean.enums.OfflineHandleEventStatus;
import com.yami.shop.bean.enums.OfflineHandleEventType;
import com.yami.shop.bean.event.BalanceCouponEvent;
import com.yami.shop.bean.event.ScoreOrderEvent;
import com.yami.shop.bean.model.OfflineHandleEvent;
import com.yami.shop.bean.param.OfflineHandleEventAuditParam;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.util.PageAdapter;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.coupon.common.constants.CouponStatusEnum;
import com.yami.shop.coupon.common.constants.ValidTimeTypeEnum;
import com.yami.shop.coupon.common.dao.CouponMapper;
import com.yami.shop.coupon.common.dao.CouponProdMapper;
import com.yami.shop.coupon.common.dao.CouponUserMapper;
import com.yami.shop.coupon.common.model.Coupon;
import com.yami.shop.coupon.common.model.CouponProd;
import com.yami.shop.coupon.common.model.CouponUser;
import com.yami.shop.coupon.common.service.CouponService;
import com.yami.shop.coupon.common.service.CouponUserService;
import com.yami.shop.dao.ProductMapper;
import com.yami.shop.service.OfflineHandleEventService;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;
/**
 * @author lgh on 2018/12/27.
 */
@Service
@AllArgsConstructor
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements CouponService {
    private final CouponMapper couponMapper;
    private final CouponProdMapper couponProdMapper;
    private final CouponUserMapper couponUserMapper;
    private final CouponUserService couponUserService;
    private final ProductMapper productMapper;
    private final OfflineHandleEventService offlineHandleEventService;
    private final ApplicationContext applicationContext;
    private final MapperFacade mapperFacade;
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "couponAndCouponProds", key = "#coupon.shopId")
    public void updateCouponAndCouponProds(@Valid Coupon coupon) {
        Integer suitableProdType = coupon.getSuitableProdType();
        Coupon couponDb = couponMapper.selectById(coupon.getCouponId());
        checkInfo(coupon, false);
        boolean isPutOn = Objects.equals(couponDb.getPutonStatus(), CouponStatusEnum.NOT_LAUNCH.getValue()) && Objects.equals(coupon.getPutonStatus(), CouponStatusEnum.PUT_ON.getValue());
        if (isPutOn) {
            coupon.setLaunchTime(new Date());
        }
        couponMapper.updateCoupon(coupon);
        // 删除该优惠券下所有商品
        couponProdMapper.deleteCouponProdsByCouponId(coupon.getCouponId());
        if (suitableProdType != 0) {
            List<Long> prodIds = coupon.getCouponProds().stream().map(CouponProd::getProdId).collect(Collectors.toList());
            // 插入所有商品
            couponProdMapper.insertCouponProdsBatch(coupon.getCouponId(), prodIds);
        }
        // 不是平台端的优惠券、修改后的领取类型为平台发放、没有发生领取类型变更的,直接返回
        if(!Objects.equals(coupon.getShopId(), Constant.PLATFORM_SHOP_ID)
                || Objects.equals(coupon.getGetWay(), 1)
                || Objects.equals(coupon.getGetWay(), couponDb.getGetWay())) {
            return;
        }
        // 处理优惠券类型从系统发放变更为用户领取时,移除用户等级绑定的优惠券(目前用户等级绑定的优惠券只支持系统发放)
        applicationContext.publishEvent(new BalanceCouponEvent(coupon.getCouponId()));
    }
    @Override
    @CacheEvict(cacheNames = "couponAndCouponProds", key = "#shopId")
    public void removeCouponAndCouponProdsCache(Long shopId) {
    }
    @Override
    public IPage<CouponDto> getCouponList(Page<CouponDto> page, String userId) {
        //获取优惠券列表
        List<Long> couponIds = couponMapper.getShopAvailableCouponIds(new PageAdapter(page));
        page.setTotal(couponMapper.countCouponPageByCouponDto());
        if (CollUtil.isEmpty(couponIds)) {
            page.setRecords(new ArrayList<>());
            return page;
        }
        List<CouponDto> couponDtoList = couponMapper.getCouponList(couponIds, I18nMessage.getDbLang());
        List<CouponUser> couponUsers = couponUserMapper.listByCouponIdsAndUserId(couponIds, userId);
        Map<Long, Integer> couponUserMap = couponUsers.stream().collect(Collectors.toMap(CouponUser::getCouponId, CouponUser::getCurUserReceiveCount));
        for (CouponDto couponDto : couponDtoList) {
            if (couponUserMap.containsKey(couponDto.getCouponId())) {
                couponDto.setCurUserReceiveCount(couponUserMap.get(couponDto.getCouponId()));
                continue;
            }
            couponDto.setCurUserReceiveCount(0);
        }
        page.setRecords(couponDtoList);
        return page;
    }
    @Override
    public IPage<CouponDto> getCouponList(Page<CouponDto> page) {
        //获取优惠券列表
        page.setTotal(couponMapper.countCouponPageByCouponDto());
        List<Long> couponIds = couponMapper.getShopAvailableCouponIds(new PageAdapter(page));
        if (CollUtil.isEmpty(couponIds)) {
            page.setRecords(new ArrayList<>());
            return page;
        }
        List<CouponDto> couponDtoList = couponMapper.getCouponList(couponIds, I18nMessage.getDbLang());
        page.setRecords(couponDtoList);
        return page;
    }
    @Override
    public IPage<CouponUser> getPageByUserId(PageParam<CouponUser> page, String userId, Integer status) {
        return couponUserMapper.getPageByUserId(page, userId, status);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
//    @CacheEvict(cacheNames = "couponAndCouponProds", key = "#shopId")
    public void batchBindCouponByIds(List<Long> couponIds, String userId, Long shopId) {
        List<CouponUser> couponUsers = new ArrayList<>();
        Collection<Coupon> coupons = listByIds(couponIds);
        if (CollectionUtils.isEmpty(coupons)) {
            return;
        }
        for (Coupon coupon : coupons) {
            CouponUser couponUser = getCouponUser(userId, coupon, 1);
            if (couponUser == null) {
                continue;
            }
            couponUsers.add(couponUser);
            // 更新库存
            if (couponMapper.updateCouponStocksAndVersion(coupon.getCouponId()) < 1) {
                // 优惠券库存不足
                throw new YamiShopBindException("yami.coupon.stock.enough");
            }
        }
        couponUserService.saveBatch(couponUsers);
    }
    @Override
    public void bindCouponById(Long couponId, String userId, Integer couponNums, Long shopId) {
        Coupon coupon = getById(couponId);
        if (Objects.isNull(coupon)) {
            throw new YamiShopBindException("yami.coupon.no.exist");
        }
        CouponUser couponUser = getCouponUser(userId, coupon, couponNums);
        if (couponUser == null) {
            return;
        }
        List<CouponUser> couponUsers = new ArrayList<>(couponNums);
        for (Integer i = 0; i < couponNums; i++) {
            CouponUser copyCouponUser = mapperFacade.map(couponUser, CouponUser.class);
            couponUsers.add(copyCouponUser);
        }
        couponUserService.saveBatch(couponUsers, couponNums);
    }
    /**
     *  生成用户优惠券绑定对象
     * @param userId     用户id
     * @param coupon     优惠券详情
     * @param couponNums 优惠券发放数量
     * @return
     */
    private CouponUser getCouponUser(String userId, Coupon coupon, int couponNums) {
        Date nowTime = new Date();
        // 当优惠券状态不为投放时
        if (coupon.getOverdueStatus() == 0 || coupon.getPutonStatus() != 1 || coupon.getStocks() == 0) {
            // 该券无法被领取或者该券领完了!
            log.warn("yami.coupon.receive.finish");
            return null;
        }
        int count = couponUserMapper.selectCount(new LambdaQueryWrapper<CouponUser>().eq(CouponUser::getUserId, userId).eq(CouponUser::getCouponId, coupon.getCouponId()));
        if (count + couponNums > coupon.getLimitNum()) {
            // 该券已达个人领取上限,无法继续领取!
            log.warn("yami.coupon.user.limit");
            return null;
        }
        CouponUser couponUser = new CouponUser();
        couponUser.setUserId(userId);
        couponUser.setStatus(1);
        couponUser.setCouponId(coupon.getCouponId());
        couponUser.setReceiveTime(nowTime);
        // 生效时间类型为固定时间
        if (coupon.getValidTimeType() == 1) {
            couponUser.setUserStartTime(coupon.getStartTime());
            couponUser.setUserEndTime(coupon.getEndTime());
        }
        // 生效时间类型为领取后生效
        if (coupon.getValidTimeType() == 2) {
            if (coupon.getAfterReceiveDays() == null) {
                coupon.setAfterReceiveDays(0);
            }
            if (coupon.getValidDays() == null) {
                coupon.setValidDays(0);
            }
            couponUser.setUserStartTime(DateUtils.addDays(DateUtil.beginOfDay(nowTime), coupon.getAfterReceiveDays()));
            couponUser.setUserEndTime(DateUtils.addDays(couponUser.getUserStartTime(), coupon.getValidDays() + 1));
        }
        couponUser.setIsDelete(0);
        return couponUser;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "couponAndCouponProds", key = "#coupon.shopId")
    public void insertCouponAndCouponProds(@Valid Coupon coupon) {
        Integer suitableProdType = coupon.getSuitableProdType();
        checkInfo(coupon, true);
        if(Objects.equals(coupon.getPutonStatus(), CouponStatusEnum.PUT_ON.getValue())) {
            coupon.setLaunchTime(new Date());
        }
        couponMapper.insert(coupon);
        if (suitableProdType != 0) {
            List<Long> prodIds = coupon.getCouponProds().stream().map(CouponProd::getProdId).collect(Collectors.toList());
            // 插入所有商品
            couponProdMapper.insertCouponProdsBatch(coupon.getCouponId(), prodIds);
        }
    }
    @Override
    public Coupon getCouponAndCouponProdsByCouponId(Long id) {
        return couponMapper.getCouponAndCouponProdsByCouponId(id);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "couponAndCouponProds", key = "#coupon.shopId")
    public void receive(Coupon coupon, String userId) {
        //如果是积分商品,就扣除用户相应的积分
        if (Objects.equals(coupon.getCouponType(), CouponType.C2P.value())) {
            applicationContext.publishEvent(new ScoreOrderEvent(coupon.getCouponId(), null, coupon.getScorePrice()));
        }
        CouponUser couponUser = getCouponUser(coupon, userId);
        couponUserMapper.insert(couponUser);
        // 更新库存
        if (couponMapper.updateCouponStocksAndVersion(coupon.getCouponId()) < 1) {
            // 优惠券库存不足
            throw new YamiShopBindException("yami.coupon.stock.enough");
        }
    }
    private CouponUser getCouponUser(Coupon coupon, String userId) {
        Date nowTime = new Date();
        // 当优惠券状态不为投放时
        if (coupon.getOverdueStatus() == 0 || coupon.getPutonStatus() != 1) {
            // 该券无法被领取
            throw new YamiShopBindException("yami.coupon.receive.finish");
        }
        // 当优惠券不在规定时间内(类型为固定时间) 优惠券使用时间,不是领取时间,一般优惠券都是可以领,还不能用的
//        if (coupon.getValidTimeType() == 1 && (coupon.getEndTime().getTime() < nowTime.getTime() || coupon.getStartTime().getTime() > nowTime.getTime())) {
//            throw new YamiShopBindException("不在可领取的时间范围内");
//        }
        // 当优惠券无库存时
        if (coupon.getStocks() == 0) {
            // 该券领完了
            throw new YamiShopBindException("yami.coupon.receive.finish");
        }
        int count = couponUserMapper.selectCount(new LambdaQueryWrapper<CouponUser>().eq(CouponUser::getUserId, userId).eq(CouponUser::getCouponId, coupon.getCouponId()));
        if (count >= coupon.getLimitNum()) {
            // 该券已达个人领取上限,无法继续领取
            throw new YamiShopBindException("yami.coupon.user.limit");
        }
        CouponUser couponUser = new CouponUser();
        couponUser.setUserId(userId);
        couponUser.setCouponId(coupon.getCouponId());
        couponUser.setStatus(1);
        couponUser.setReceiveTime(nowTime);
        // 生效时间类型为固定时间
        if (coupon.getValidTimeType() == 1) {
            couponUser.setUserStartTime(coupon.getStartTime());
            couponUser.setUserEndTime(coupon.getEndTime());
        }
        // 生效时间类型为领取后生效
        if (coupon.getValidTimeType() == ValidTimeTypeEnum.RECEIVE.getValue()) {
            if (coupon.getAfterReceiveDays() == null) {
                coupon.setAfterReceiveDays(0);
            }
            if (coupon.getValidDays() == null) {
                coupon.setValidDays(0);
            }
            couponUser.setUserStartTime(DateUtils.addDays(DateUtil.beginOfDay(nowTime), coupon.getAfterReceiveDays()));
            couponUser.setUserEndTime(DateUtils.addDays(couponUser.getUserStartTime(), coupon.getValidDays() + 1));
        }
        couponUser.setIsDelete(0);
        return couponUser;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeCoupon(Date now) {
        // 设置店铺的过期优惠券为过期状态
        couponMapper.updateOverdueStatusByTime(now);
        // 设置店铺库存为0优惠券的状态(设为未投放状态) 没库存就消失么?
        // 像京东会有没库存的优惠券,一直展示大半天,也不消失,所以消失是用户手动下线的
//        couponMapper.updatePutonStatusByStocks();
    }
    @Override
    public void putonCoupon(Date now) {
        couponMapper.putonCoupon(now);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByCouponId(Long couponId) {
        // 获取未被删除的优惠券数量
        Integer useCount = couponUserMapper.selectCount(new LambdaQueryWrapper<CouponUser>().eq(CouponUser::getCouponId, couponId).eq(CouponUser::getIsDelete, 0));
        if (useCount > 0) {
            // 该优惠券已被领取,删除失败
            throw new YamiShopBindException("yami.coupon.delete.check1");
        }
        Coupon coupon = couponMapper.selectById(couponId);
        if (Objects.isNull(coupon)) {
            // 优惠券不存在
            throw new YamiShopBindException("yami.coupon.no.exist");
        }
        if (Objects.equals(coupon.getPutonStatus(), 1)) {
            //  该优惠券已投放,删除失败
            throw new YamiShopBindException("yami.coupon.delete.check2");
        }
        //删除优惠券关联的商品
        couponProdMapper.delete(new LambdaQueryWrapper<CouponProd>().eq(CouponProd::getCouponId, couponId));
        //删除优惠券
        couponMapper.deleteById(couponId);
    }
    @Override
    public List<CouponDto> generalCouponList(String userId) {
        return couponMapper.generalCouponList(userId);
    }
    @Override
    public List<CouponDto> generalCouponList() {
        return couponMapper.generalCouponListTourist();
    }
    @Override
    public IPage<CouponDto> getCouponListByStatus(IPage<CouponDto> page, String userId, Integer status) {
        IPage<CouponDto> couponPage = couponMapper.getCouponListByStatus(page, userId, status);
        List<CouponDto> couponDtoList = couponPage.getRecords();
        for (CouponDto couponDto : couponDtoList) {
            if (Objects.equals(couponDto.getValidTimeType(), 2)) {
                Integer afterReceiveDays = couponDto.getAfterReceiveDays();
                if (Objects.isNull(couponDto.getAfterReceiveDays())) {
                    afterReceiveDays = 0;
                }
                Integer validDays = couponDto.getValidDays();
                if (validDays == null) {
                    validDays = 0;
                }
                couponDto.setStartTime(DateUtil.offsetDay(couponDto.getReceiveTime(), afterReceiveDays));
                couponDto.setEndTime(DateUtil.offsetDay(couponDto.getStartTime(), validDays));
            }
        }
        return couponPage;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "CouponAndCouponUser", key = "#userId")
    public void deleteUserCouponByCouponId(String userId, Long couponId) {
        couponUserMapper.deleteUserCoupon(userId, couponId);
    }
    @Override
    public List<CouponOrderDto> getCouponListByShopIds(String userId, Long shopId) {
        List<CouponOrderDto> couponOrderDtoList = couponMapper.getCouponListByShopIds(userId, shopId);
        for (CouponOrderDto couponOrderDto : couponOrderDtoList) {
            if (Objects.equals(couponOrderDto.getValidTimeType(), 2)) {
                Integer validDays = couponOrderDto.getValidDays();
                if (validDays == null) {
                    validDays = 0;
                }
                Integer afterReceiveDays = couponOrderDto.getAfterReceiveDays();
                if (afterReceiveDays == null) {
                    afterReceiveDays = 0;
                }
                couponOrderDto.setStartTime(DateUtil.offsetDay(couponOrderDto.getReceiveTime(), afterReceiveDays));
                couponOrderDto.setEndTime(DateUtil.offsetDay(couponOrderDto.getStartTime(), validDays));
            }
        }
        return couponOrderDtoList;
    }
    @Override
    @Cacheable(cacheNames = "couponAndCouponProds", key = "#shopId")
    public List<Coupon> listPutonByShopId(Long shopId) {
        return couponMapper.listPutonCouponAndCouponProdsByShopId(shopId);
    }
    @Override
    public List<CouponDto> listCouponIdsByUserId(String userId) {
        return couponMapper.listCouponIdsByUserId(userId);
    }
    @Override
    public IPage<ProductDto> prodListByCoupon(PageParam<ProductDto> page, Coupon coupon, Integer dbLang) {
        // 优惠券所有商品可用、指定商品可用、指定商品不可用 (0全部商品参与 1指定商品参与 2指定商品不参与)
        IPage<ProductDto> productPage;
        if (coupon.getSuitableProdType() == 0) {
            productPage = productMapper.listByShopId(page, coupon.getShopId(), dbLang);
        } else {
            productPage = productMapper.listBySuitableProdTypeAndCouponIdAndShopId(page, coupon.getShopId(), coupon.getSuitableProdType(),
                    coupon.getCouponId(), dbLang);
        }
        return productPage;
    }
    @Override
    public IPage<Coupon> getMultiShopPage(PageParam<Coupon> page, Coupon coupon) {
        IPage<Coupon> multiShopPage = couponMapper.getMultiShopPage(page, coupon);
        for (Coupon record : multiShopPage.getRecords()) {
            record.setUseNum(couponMapper.countUseNum(record.getCouponId()) == null ? 0 : couponMapper.countUseNum(record.getCouponId()));
            record.setTakeNum(couponMapper.countTakeNum(record.getCouponId(), record.getShopId()) == null ? 0 : couponMapper.countTakeNum(record.getCouponId(), record.getShopId()));
        }
        return multiShopPage;
    }
    @Override
    public Map<String, Long> getCouponCountByStatus(String userId) {
        return couponMapper.getCouponCountByStatus(userId);
    }
    @Override
    public IPage<Coupon> getPlatformPage(PageParam<Coupon> page, Coupon coupon) {
        IPage<Coupon> couponPage = couponMapper.getPlatformPage(page, coupon);
        List<Coupon> couponList = couponPage.getRecords();
        for (Coupon temp : couponList) {
            temp.setTakeNum(couponMapper.countTakeNum(temp.getCouponId(), temp.getShopId()) == null ? 0 : couponMapper.countTakeNum(temp.getCouponId(), temp.getShopId()));
            temp.setUseNum(couponMapper.countUseNum(temp.getCouponId()) == null ? 0 : couponMapper.countUseNum(temp.getCouponId()));
        }
        return couponPage;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = "couponAndCouponProds", key = "#coupon.shopId")
    public void offline(Coupon coupon, String offlineReason, Long sysUserId) {
        // 添加下线处理记录
        OfflineHandleEvent handleEvent = offlineHandleEventService.getBaseMapper().selectOne(new LambdaUpdateWrapper<OfflineHandleEvent>()
                .eq(OfflineHandleEvent::getHandleId, coupon.getCouponId())
                .eq(OfflineHandleEvent::getHandleType, OfflineHandleEventType.COUPON.getValue())
                .ne(OfflineHandleEvent::getStatus, OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())
        );
        if (Objects.isNull(handleEvent)) {
            handleEvent = new OfflineHandleEvent();
        }
        Date now = new Date();
        handleEvent.setHandleId(coupon.getCouponId());
        handleEvent.setHandleType(OfflineHandleEventType.COUPON.getValue());
        handleEvent.setCreateTime(now);
        handleEvent.setOfflineReason(offlineReason);
        handleEvent.setHandlerId(sysUserId);
        handleEvent.setShopId(coupon.getShopId());
        handleEvent.setStatus(OfflineHandleEventStatus.OFFLINE_BY_PLATFORM.getValue());
        handleEvent.setUpdateTime(now);
        if (Objects.nonNull(handleEvent.getEventId())) {
            offlineHandleEventService.updateById(handleEvent);
        } else {
            offlineHandleEventService.save(handleEvent);
        }
        // 更新活动状态为下线
        couponMapper.updatePutOnStatusByCouponId(coupon.getCouponId(), CouponStatusEnum.OFFLINE.getValue());
        //更新优惠券过期状态为过期
        couponMapper.updateOverdueStatusByCouponId(coupon.getCouponId(), 0);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditCoupon(OfflineHandleEventAuditParam offlineHandleEventAuditParam, Long sysUserId) {
        // 审核通过
        if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            // 更新优惠券为暂不投放状态
            couponMapper.updatePutOnStatusByCouponId(offlineHandleEventAuditParam.getHandleId(), CouponStatusEnum.NOT_LAUNCH.getValue());
            //更新优惠券过期状态为未过期
            couponMapper.updateOverdueStatusByCouponId(offlineHandleEventAuditParam.getHandleId(), 1);
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            couponMapper.updatePutOnStatusByCouponId(offlineHandleEventAuditParam.getHandleId(), CouponStatusEnum.OFFLINE.getValue());
        }
        offlineHandleEventService.auditOfflineEvent(offlineHandleEventAuditParam, sysUserId);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditApply(Long eventId, Long couponId, String reapplyReason) {
        // 更新活动为待审核状态
        couponMapper.updatePutOnStatusByCouponId(couponId, CouponStatusEnum.WAIT_AUDIT.getValue());
        // 更新事件状态
        offlineHandleEventService.updateToApply(eventId, reapplyReason);
    }
    private void checkInfo(Coupon coupon, Boolean isSave) {
        boolean checkProd = (Objects.equals(CouponProdType.PROD_IN.value(), coupon.getSuitableProdType())
                || Objects.equals(CouponProdType.PROD_NO_IN.value(), coupon.getSuitableProdType()))
                && CollectionUtils.isEmpty(coupon.getCouponProds());
        if (checkProd) {
            // 商品不能为空
            throw new YamiShopBindException("yami.product.no.exist");
        }
        // 判断投放时间 < 生效时间
        if(coupon.getLaunchTime() != null
                && coupon.getEndTime() != null
                && coupon.getLaunchTime().compareTo(coupon.getEndTime()) > 0) {
            throw new YamiShopBindException("yami.coupon.launch.time.lt.endtime");
        }
        if (Objects.equals(coupon.getPutonStatus(), CouponStatusEnum.AUTO_LAUNCH.getValue()) && Objects.isNull(coupon.getLaunchTime())) {
            // 优惠券投放时间不能为空
            throw new YamiShopBindException("yami.coupon.launch.time.check");
        }
        Date nowTime = new Date();
        if (Objects.nonNull(coupon.getLaunchTime()) && coupon.getLaunchTime().getTime() < nowTime.getTime()) {
            // 投放时间需大于当前时间
            throw new YamiShopBindException("yami.coupon.launch.time.check1");
        }
        if (isSave) {
            if (coupon.getLimitNum() <= 0) {
                // 优惠券限领数量需大于0
                throw new YamiShopBindException("yami.coupon.limit.check");
            }
            if (coupon.getValidTimeType() == 1 && coupon.getStartTime().getTime() > coupon.getEndTime().getTime()) {
                // 开始时间需大于结束时间
                throw new YamiShopBindException("yami.coupon.time.check");
            }
        }
        // 结束时间小于等于当前时间
        if (Objects.equals(coupon.getValidTimeType(), ValidTimeTypeEnum.FIXED.value())) {
            if (coupon.getEndTime().getTime() < nowTime.getTime()) {
                coupon.setOverdueStatus(0);
                coupon.setPutonStatus(CouponStatusEnum.CANCEL.getValue());
            } else {
                coupon.setOverdueStatus(1);
            }
        }
    }
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/impl/CouponUseRecordServiceImpl.java
New file
@@ -0,0 +1,120 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yami.shop.bean.model.Order;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ResponseEnum;
import com.yami.shop.coupon.common.constants.UserCouponRecordStatus;
import com.yami.shop.coupon.common.constants.UserCouponStatus;
import com.yami.shop.coupon.common.dao.CouponUseRecordMapper;
import com.yami.shop.coupon.common.dao.CouponUserMapper;
import com.yami.shop.coupon.common.dto.CouponRecordDTO;
import com.yami.shop.coupon.common.model.CouponUseRecord;
import com.yami.shop.coupon.common.service.CouponUseRecordService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.*;
/**
 * 优惠券使用情况
 *
 * @author yami code generator
 * @date 2019-05-15 09:04:57
 */
@Service
@AllArgsConstructor
public class CouponUseRecordServiceImpl extends ServiceImpl<CouponUseRecordMapper, CouponUseRecord> implements CouponUseRecordService {
    private final CouponUseRecordMapper couponUseRecordMapper;
    private final CouponUserMapper couponUserMapper;
    @Override
    public void addCouponUseRecode(List<CouponUseRecord> couponUseList) {
        couponUseRecordMapper.addCouponUseRecode(couponUseList);
    }
    @Override
    public void batchUpdateRecordByStatusAndOrderNums(int status, List<String> orderNumberList) {
        // 更新商家券、平台券
        couponUseRecordMapper.batchUpdateRecordByStatusAndOrderNums(status, orderNumberList);
    }
    @Override
    public void lockCoupon(List<CouponRecordDTO> lockCouponParams, String userId) {
        List<CouponUseRecord> couponLocks = Lists.newArrayList();
        List<Long> userCouponIds = new ArrayList<>();
        Set<Long> orderIds = new HashSet<>();
        Date now = new Date();
        for (CouponRecordDTO lockCouponParam : lockCouponParams) {
            CouponUseRecord couponLock = new CouponUseRecord();
            couponLock.setAmount(lockCouponParam.getReduceAmount());
            // 获取用户优惠券id
            couponLock.setCouponUserId(lockCouponParam.getCouponUserId());
            userCouponIds.add(lockCouponParam.getCouponUserId());
            couponLock.setUserId(userId);
            couponLock.setOrderNumber(lockCouponParam.getOrderNumbers());
            if (couponLock.getOrderNumber().contains(StrUtil.COMMA)) {
                for (String orderId : couponLock.getOrderNumber().split(StrUtil.COMMA)) {
                    orderIds.add(Long.valueOf(orderId));
                }
            } else {
                orderIds.add(Long.valueOf(couponLock.getOrderNumber()));
            }
            //优惠券记录为冻结状态
            couponLock.setStatus(UserCouponRecordStatus.FREEZE.getValue());
            couponLock.setUseTime(now);
            couponLocks.add(couponLock);
        }
        // 批量保存使用记录
        saveBatch(couponLocks);
        // 批量将用户的优惠券变成已使用状态
        couponUserMapper.batchUpdateUserCouponStatus(UserCouponStatus.USED.getValue(), userCouponIds);
//        // 发送消息一个小时后解锁优惠券(包括哪些订单)
//        SendStatus sendStatus = couponMqTemplate.syncSend(RocketMqConstant.COUPON_UNLOCK_TOPIC, new GenericMessage<>(orderIds), RocketMqConstant.TIMEOUT, RocketMqConstant.CANCEL_ORDER_DELAY_LEVEL + 1).getSendStatus();
//        if (!Objects.equals(sendStatus,SendStatus.SEND_OK)) {
//            // 消息发不出去就抛异常,发的出去无所谓
//            throw new YamiShopBindException(ResponseEnum.EXCEPTION);
//        }
    }
    @Override
    public void unlockCoupon(Order order) {
        // 该订单没有下单成功,或订单已取消,赶紧解锁库存
        //查询订单所使用的优惠券列表
        List<CouponUseRecord> couponUseRecordList = couponUseRecordMapper.selectList(new LambdaQueryWrapper<CouponUseRecord>()
                .eq(CouponUseRecord::getUserId, order.getUserId())
                .like(CouponUseRecord::getOrderNumber, order.getOrderNumber()));
        List<Long> couponUserIds = Lists.newArrayList();
        for (CouponUseRecord couponUseRecord : couponUseRecordList) {
            couponUserIds.add(couponUseRecord.getCouponUserId());
        }
        if (CollectionUtil.isEmpty(couponUserIds)) {
            return;
        }
        // 批量将用户的优惠券变成未使用状态
        couponUserMapper.batchUpdateUserCouponStatus(UserCouponStatus.EFFECTIVE.getValue(), couponUserIds);
        // 将锁定状态标记为已解锁
        int updateStatus = couponUseRecordMapper.unLockByIds(couponUserIds);
        if (updateStatus == 0) {
            throw new YamiShopBindException(ResponseEnum.EXCEPTION);
        }
    }
}
yami-shop-coupon/yami-shop-coupon-common/src/main/java/com/yami/shop/coupon/common/service/impl/CouponUserServiceImpl.java
New file
@@ -0,0 +1,178 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.common.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.param.*;
import com.yami.shop.common.util.DateParam;
import com.yami.shop.common.util.DateUtils;
import com.yami.shop.coupon.common.dao.CouponUseRecordMapper;
import com.yami.shop.coupon.common.dao.CouponUserMapper;
import com.yami.shop.coupon.common.model.CouponUseRecord;
import com.yami.shop.coupon.common.model.CouponUser;
import com.yami.shop.coupon.common.service.CouponUserService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/**
 * @author lgh on 2018/12/27.
 */
@Service
public class CouponUserServiceImpl extends ServiceImpl<CouponUserMapper, CouponUser> implements CouponUserService {
    @Autowired
    private CouponUserMapper couponUserMapper;
    @Autowired
    private CouponUseRecordMapper couponUseRecordMapper;
//    @Override
//    public List<CouponUser> getCouponAndCouponUserByCouponUserIds(List<Long> couponUserIds) {
//        if (CollectionUtil.isEmpty(couponUserIds)) {
//            return Collections.emptyList();
//        }
//        return couponUserMapper.getCouponAndCouponUserByCouponUserIds(couponUserIds);
//    }
    @Override
    public void deleteUnValidTimeCoupons(Date date) {
        couponUserMapper.deleteUnValidTimeCoupons(date);
    }
    @Override
    public void updateStatusByTime(Date now) {
        couponUserMapper.updateStatusByTime(now);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrder(String userId, String orderNumber) {
        //查询订单所使用的优惠券列表
        List<CouponUseRecord> couponUseRecordList = couponUseRecordMapper.selectList(new LambdaQueryWrapper<CouponUseRecord>()
                .eq(CouponUseRecord::getUserId, userId)
                .like(CouponUseRecord::getOrderNumber, orderNumber));
        if (CollectionUtils.isEmpty(couponUseRecordList)) {
            return;
        }
        List<Long> couponUseRecordIdList = Lists.newArrayList();
        List<Long> couponUserIds = Lists.newArrayList();
        for (CouponUseRecord couponUseRecord : couponUseRecordList) {
            String[] split = couponUseRecord.getOrderNumber().split(StrUtil.COMMA);
            // 订单号集合
            StringBuilder orderNumbers = new StringBuilder(100);
            // 如果大于1则是平台优惠券,并且在多个店铺使用时
            if(split.length > 1){
                for (String orderNumStr : split) {
                    // 判断是不是当前的订单编号
                    if(StrUtil.equals(orderNumStr,orderNumber)){
                        continue;
                    }
                    orderNumbers.append(orderNumStr).append(StrUtil.COMMA);
                }
                orderNumbers.deleteCharAt(orderNumbers.length() - 1);
                // 修改订单编号信息,在进行修改后结束本次循环
                couponUseRecord.setOrderNumber(orderNumbers.toString());
                couponUseRecordMapper.updateById(couponUseRecord);
                continue;
            }
            couponUseRecordIdList.add(couponUseRecord.getCouponUseRecordId());
            couponUserIds.add(couponUseRecord.getCouponUserId());
        }
        if(CollectionUtil.isNotEmpty(couponUseRecordIdList)) {
            //删除优惠券使用记录
            couponUseRecordMapper.deleteBatchIds(couponUseRecordIdList);
        }
        if(CollectionUtil.isNotEmpty(couponUserIds)) {
            //修改用户优惠券状态为可用状态
            couponUserMapper.batchUpdateUserCouponStatus(1, couponUserIds);
        }
    }
    @Override
    public List<CouponAnalysisParam> getCouponAnalysis(ProdEffectParam param) {
        List<CouponAnalysisParam> resList = new ArrayList<>();
        List<DateParam> everyDays = DateUtils.findEveryDays(param.getStartTime(), param.getEndTime());
        for (DateParam everyDay : everyDays) {
            CouponAnalysisParam res = new CouponAnalysisParam();
            param.setStartTime(everyDay.getStartTime());
            param.setEndTime(everyDay.getEndTime());
            res.setCurrentDay(DateUtils.dateToStrYmd(param.getStartTime()));
            // 领取次数
            res.setTakeNum(couponUserMapper.countTakeNum(null,null, param));
            // TODO 验证次数
            // 微商城使用次数
            res.setUseNum(couponUserMapper.countTakeNum(null,2, param));
            // TODO 分享次数
            resList.add(res);
        }
        return resList;
    }
    @Override
    public Integer countMemberGetCoupon(CustomerReqParam param) {
        return couponUserMapper.countMemberGetCoupon(param);
    }
    @Override
    public Integer countMemberCouponByParam(MemberReqParam param) {
        return couponUserMapper.countMemberCouponByParam(param);
    }
    @Override
    public CouponUserParam getCouponCountByUserId(String userId) {
        // 用户未使用的并且是未过期的优惠券
        Date now = new Date();
        Integer usables = couponUserMapper.countCouponUsableNums(userId,now);
        // 已使用
        Integer usedNums = couponUserMapper.countCouponUsedNums(userId);
        // 失效(已过期)
        Integer couponExpiredNums = couponUserMapper.countCouponExpiredNums(userId);
        CouponUserParam param = new CouponUserParam();
        param.setCouponUsableNums(getIntegerNum(usables));
        param.setCouponUsedNums(getIntegerNum(usedNums));
        param.setCouponExpiredNums(getIntegerNum(couponExpiredNums));
        return param;
    }
    @Override
    public Page<CouponAnalysisParam> getCouponAnalysisParamByDate(Page page, ProdEffectParam param) {
        Page<CouponAnalysisParam> paramByDate = couponUserMapper.getCouponAnalysisParamByDate(page, param);
        for (CouponAnalysisParam couponAnalysisParam : paramByDate.getRecords()) {
            couponAnalysisParam.setUseNum(couponUserMapper.countUseNum(couponAnalysisParam.getCouponId(),param));
        }
        return paramByDate;
    }
    private Integer getIntegerNum(Integer value) {
        if (Objects.isNull(value)){
            value = 0;
        }
        return value;
    }
    @Override
    public CouponUserParam getCouponCountInfo(String userId, Long shopId) {
        return couponUserMapper.getCouponCountInfo(userId, shopId);
    }
}
yami-shop-coupon/yami-shop-coupon-common/src/main/resources/mapper/CouponMapper.xml
New file
@@ -0,0 +1,522 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yami.shop.coupon.common.dao.CouponMapper">
    <resultMap id="BaseResultMap" type="com.yami.shop.coupon.common.model.Coupon">
        <!--
          WARNING - @mbg.generated
        -->
        <id column="coupon_id" jdbcType="BIGINT" property="couponId"/>
        <result column="shop_id" jdbcType="BIGINT" property="shopId"/>
        <result column="coupon_name" jdbcType="VARCHAR" property="couponName"/>
        <result column="sub_title" jdbcType="VARCHAR" property="subTitle"/>
        <result column="coupon_type" jdbcType="TINYINT" property="couponType"/>
        <result column="cash_condition" jdbcType="DECIMAL" property="cashCondition"/>
        <result column="reduce_amount" jdbcType="DECIMAL" property="reduceAmount"/>
        <result column="coupon_discount" jdbcType="DECIMAL" property="couponDiscount"/>
        <result column="valid_time_type" jdbcType="TINYINT" property="validTimeType"/>
        <result column="launch_time" jdbcType="TIMESTAMP" property="launchTime"/>
        <result column="start_time" jdbcType="TIMESTAMP" property="startTime"/>
        <result column="end_time" jdbcType="TIMESTAMP" property="endTime"/>
        <result column="after_receive_days" jdbcType="INTEGER" property="afterReceiveDays"/>
        <result column="valid_days" jdbcType="INTEGER" property="validDays"/>
        <result column="stocks" jdbcType="INTEGER" property="stocks"/>
        <result column="source_stock" jdbcType="INTEGER" property="sourceStock"/>
        <result column="suitable_prod_type" jdbcType="TINYINT" property="suitableProdType"/>
        <result column="limit_num" jdbcType="INTEGER" property="limitNum"/>
        <result column="version" jdbcType="INTEGER" property="version"/>
        <result column="is_score_type" jdbcType="INTEGER" property="isScoreType"/>
        <result column="score_price" jdbcType="INTEGER" property="scorePrice"/>
        <result column="overdue_status" jdbcType="TINYINT" property="overdueStatus"/>
        <result column="puton_status" jdbcType="TINYINT" property="putonStatus"/>
    </resultMap>
    <resultMap id="CouponAndCouponProdMap" type="com.yami.shop.coupon.common.model.Coupon">
        <id column="coupon_id" jdbcType="BIGINT" property="couponId"/>
        <result column="shop_id" jdbcType="BIGINT" property="shopId"/>
        <result column="coupon_name" jdbcType="VARCHAR" property="couponName"/>
        <result column="sub_title" jdbcType="VARCHAR" property="subTitle"/>
        <result column="get_way" jdbcType="TINYINT" property="getWay"/>
        <result column="coupon_type" jdbcType="TINYINT" property="couponType"/>
        <result column="cash_condition" jdbcType="DECIMAL" property="cashCondition"/>
        <result column="reduce_amount" jdbcType="DECIMAL" property="reduceAmount"/>
        <result column="coupon_discount" jdbcType="DECIMAL" property="couponDiscount"/>
        <result column="valid_time_type" jdbcType="TINYINT" property="validTimeType"/>
        <result column="launch_time" jdbcType="TIMESTAMP" property="launchTime"/>
        <result column="start_time" jdbcType="TIMESTAMP" property="startTime"/>
        <result column="end_time" jdbcType="TIMESTAMP" property="endTime"/>
        <result column="after_receive_days" jdbcType="INTEGER" property="afterReceiveDays"/>
        <result column="valid_days" jdbcType="INTEGER" property="validDays"/>
        <result column="stocks" jdbcType="INTEGER" property="stocks"/>
        <result column="source_stock" jdbcType="INTEGER" property="sourceStock"/>
        <result column="suitable_prod_type" jdbcType="TINYINT" property="suitableProdType"/>
        <result column="limit_num" jdbcType="INTEGER" property="limitNum"/>
        <result column="version" jdbcType="INTEGER" property="version"/>
        <result column="overdue_status" jdbcType="TINYINT" property="overdueStatus"/>
        <result column="puton_status" jdbcType="TINYINT" property="putonStatus"/>
        <collection property="couponProds" ofType="com.yami.shop.coupon.common.model.CouponProd">
            <id column="coupon_prod_id" jdbcType="BIGINT" property="couponProdId"/>
            <!--下面注释不要打开,有bug-->
            <!--<result column="coupon_id" jdbcType="BIGINT" property="couponId"/>-->
            <result column="prod_id" jdbcType="BIGINT" property="prodId"/>
            <result column="prod_name" jdbcType="VARCHAR" property="prodName"/>
            <result column="pic" jdbcType="VARCHAR" property="pic"/>
        </collection>
    </resultMap>
    <resultMap id="couponOrderDtoMap" type="com.yami.shop.bean.app.dto.CouponOrderDto">
        <result column="coupon_user_id" jdbcType="BIGINT" property="couponUserId"/>
        <result column="coupon_id" jdbcType="BIGINT" property="couponId"/>
        <result column="shop_id" jdbcType="BIGINT" property="shopId"/>
        <result column="coupon_name" jdbcType="VARCHAR" property="couponName"/>
        <result column="sub_title" jdbcType="VARCHAR" property="subTitle"/>
        <result column="coupon_type" jdbcType="TINYINT" property="couponType"/>
        <result column="cash_condition" jdbcType="DECIMAL" property="cashCondition"/>
        <result column="reduce_amount" jdbcType="DECIMAL" property="reduceAmount"/>
        <result column="coupon_discount" jdbcType="DECIMAL" property="couponDiscount"/>
        <result column="user_start_time" jdbcType="TIMESTAMP" property="startTime"/>
        <result column="user_end_time" jdbcType="TIMESTAMP" property="endTime"/>
        <result column="suitable_prod_type" jdbcType="TINYINT" property="suitableProdType"/>
        <result column="coupon_user_id" jdbcType="BIGINT" property="couponUserId"/>
        <result column="receive_time" jdbcType="TIMESTAMP" property="receiveTime"/>
        <result column="valid_time_type" jdbcType="BIGINT" property="validTimeType"/>
        <result column="after_receive_days" jdbcType="BIGINT" property="afterReceiveDays"/>
        <result column="valid_days" jdbcType="BIGINT" property="validDays"/>
        <collection property="prodIds" javaType="java.util.List" ofType="long">
            <result column="prodIds"/>
        </collection>
    </resultMap>
    <resultMap id="couponProdDtoMap" type="com.yami.shop.bean.app.dto.CouponDto">
        <id column="coupon_id" jdbcType="BIGINT" property="couponId"/>
        <result column="shop_id" jdbcType="BIGINT" property="shopId"/>
        <result column="shop_name" jdbcType="VARCHAR" property="shopName"/>
        <result column="shop_logo" jdbcType="VARCHAR" property="shopLogo"/>
        <result column="coupon_name" jdbcType="VARCHAR" property="couponName"/>
        <result column="sub_title" jdbcType="VARCHAR" property="subTitle"/>
        <result column="coupon_type" jdbcType="TINYINT" property="couponType"/>
        <result column="cash_condition" jdbcType="DECIMAL" property="cashCondition"/>
        <result column="reduce_amount" jdbcType="DECIMAL" property="reduceAmount"/>
        <result column="coupon_discount" jdbcType="DECIMAL" property="couponDiscount"/>
        <result column="source_stock" jdbcType="INTEGER" property="sourceStock"/>
        <result column="stocks" jdbcType="INTEGER" property="stocks"/>
        <result column="start_time" jdbcType="TIMESTAMP" property="startTime"/>
        <result column="end_time" jdbcType="TIMESTAMP" property="endTime"/>
        <result column="suitable_prod_type" jdbcType="TINYINT" property="suitableProdType"/>
        <result column="coupon_user_id" jdbcType="BIGINT" property="couponUserId"/>
        <result column="receive_time" jdbcType="TIMESTAMP" property="receiveTime"/>
        <result column="valid_time_type" jdbcType="BIGINT" property="validTimeType"/>
        <result column="after_receive_days" jdbcType="BIGINT" property="afterReceiveDays"/>
        <result column="valid_days" jdbcType="BIGINT" property="validDays"/>
        <result column="cur_user_receive_count" jdbcType="BIGINT" property="curUserReceiveCount"/>
        <result column="user_use_count" jdbcType="INTEGER" property="userHasCount"/>
        <result column="limit_num" jdbcType="INTEGER" property="limitNum"/>
        <collection property="prods" javaType="java.util.List" ofType="com.yami.shop.bean.app.dto.ProductDto" column="coupon_id">
            <id column="prod_id" jdbcType="BIGINT" property="prodId"/>
            <result column="prod_name" jdbcType="VARCHAR" property="prodName"/>
            <result column="pic" jdbcType="VARCHAR" property="pic"/>
            <result column="price" jdbcType="DECIMAL" property="price"/>
        </collection>
    </resultMap>
    <select id="getCouponAndCouponProdsByCouponId" resultMap="CouponAndCouponProdMap">
        select c.*,cp.*,p.* from tz_coupon c
        left join tz_coupon_prod cp on c.coupon_id = cp.coupon_id
        left join tz_prod p on cp.prod_id = p.prod_id
        where c.coupon_id = #{id}
    </select>
    <update id="updateCouponStocksAndVersion">
    update tz_coupon set version = version + 1, stocks = stocks - 1 where coupon_id = #{couponId} and stocks > 0
  </update>
    <update id="updateOverdueStatusByTime">
    update tz_coupon set overdue_status = 0, puton_status = -1 where end_time &lt; #{now} and valid_time_type = 1
  </update>
    <update id="putonCoupon">
    update tz_coupon set puton_status = 1 where launch_time &lt;= #{now} and overdue_status = 1 and stocks &gt; 0 and puton_status = 0
  </update>
    <select id="getCouponList" resultMap="couponProdDtoMap">
        SET @tmp=NULL;
        SET @rank=NULL;
        SELECT item.*,sd.shop_logo,sd.shop_name,pl.prod_name FROM
        (
            SELECT IF(@tmp=coupon.coupon_id,@rank:=@rank + 1,@rank:=1) AS new_rank,@tmp:=coupon.coupon_id AS tmp, coupon.* FROM (
                <!--全部商品参与-->
                SELECT c.*,p.pic,p.price,p.prod_id
                FROM (SELECT * FROM tz_coupon WHERE suitable_prod_type = 0 AND coupon_id IN
                <foreach collection="couponIds" item="couponId" separator="," open="(" close=")">
                    #{couponId}
                </foreach>
                ) c
                JOIN tz_prod p ON p.status = 1 AND c.shop_id = p.shop_id AND p.prod_type &lt; 3
                UNION ALL
                <!--指定商品参与-->
                SELECT c.*,p.pic,p.price,p.prod_id
                FROM (SELECT * FROM tz_coupon WHERE suitable_prod_type = 1 AND coupon_id IN
                <foreach collection="couponIds" item="couponId" separator="," open="(" close=")">
                    #{couponId}
                </foreach>
                ) c
                LEFT JOIN tz_coupon_prod cp ON cp.`coupon_id` = c.`coupon_id`
                JOIN tz_prod p ON p.status = 1 AND p.prod_id = cp.prod_id
                UNION ALL
                <!--指定商品不参与-->
                SELECT c.*,p.pic,p.price,p.prod_id
                FROM (
                SELECT * FROM tz_coupon WHERE suitable_prod_type = 2 AND coupon_id IN
                <foreach collection="couponIds" item="couponId" separator="," open="(" close=")">
                    #{couponId}
                </foreach>
                ) c
                JOIN tz_prod p ON p.status = 1 AND p.prod_type &lt; 3 AND p.prod_id NOT IN (SELECT prod_id FROM tz_coupon_prod WHERE coupon_id = c.coupon_id) AND p.shop_id = c.shop_id
            ) AS coupon
            order by coupon.coupon_id desc
        ) AS item
        JOIN tz_shop_detail sd ON sd.shop_id = item.shop_id AND sd.shop_status = 1
        LEFT JOIN tz_prod_lang pl ON pl.prod_id = item.prod_id AND pl.lang = #{lang}
        WHERE item.new_rank IN (1,2,3) AND item.prod_id IS NOT NULL
    </select>
    <select id="getCouponListTourist" resultMap="couponProdDtoMap">
        SET @tmp=NULL;
        SET @rank=NULL;
        set @id=NULL;
        <!--指定商品参与-->
        <if test="couponForProd != null and couponForProd.size() > 0">
            SELECT pc.*
            FROM ( SELECT cp.prod_id,cp.pic,cp.price,cp.prod_name,c.*
            FROM (
            SELECT IF(@tmp=cp.coupon_id,@rank:=@rank + 1,@rank:=1) AS new_rank,@tmp:=coupon_id AS tmp,cp.coupon_prod_id,cp.coupon_id,p.prod_id,p.pic,p.price,p.prod_name
            FROM tz_coupon_prod cp
            JOIN tz_prod p ON p.prod_id = cp.`prod_id` AND p.`status` = 1
            WHERE cp.coupon_id IN
            <foreach collection="couponForProd" item="couponId" separator="," open="(" close=")">
                #{couponId}
            </foreach>
            ORDER BY cp.coupon_id
            ) AS cp
            JOIN tz_coupon c ON c.coupon_id = cp.coupon_id WHERE cp.new_rank &lt;= 3
            ) AS pc
            <if test="(couponForAllProd != null and couponForAllProd.size() > 0) or (couponForElseProd != null and couponForElseProd.size() > 0)">
                UNION
            </if>
        </if>
        <if test="(couponForAllProd != null and couponForAllProd.size() > 0) or (couponForElseProd != null and couponForElseProd.size() > 0)">
            SELECT pc.*
            FROM  (
            SELECT temp.prod_id,temp.pic,temp.price,temp.prod_name,c.*
            FROM (
            <!--全部商品参与-->
            <foreach collection="couponForAllProd" item="coupon" separator="UNION">
                (SELECT @id:=#{coupon.couponId} AS temp_id,p.* FROM tz_prod p WHERE p.status = 1 AND p.shop_id = #{coupon.shopId} LIMIT 0,3)
            </foreach>
            <if test="couponForAllProd != null and couponForAllProd.size() > 0 and couponForElseProd != null and couponForElseProd.size() > 0">
                UNION
            </if>
            <!--指定商品不参与-->
            <if test="couponForElseProd != null and couponForElseProd.size() > 0">
                <foreach collection="couponForElseProd" item="coupon" separator="UNION">
                    (SELECT @id:=#{coupon.couponId} AS temp_id,p.* FROM tz_prod p WHERE p.status = 1 AND p.shop_id = #{coupon.shopId}
                    AND p.prod_id NOT IN (SELECT prod_id FROM tz_coupon_prod WHERE coupon_id = #{coupon.couponId}) LIMIT 0,3)
                </foreach>
            </if>
            ) AS temp
            JOIN tz_coupon c
            ON c.coupon_id = temp.temp_id
            ) AS pc
        </if>
    </select>
    <!--<select id="generalCouponList" resultType="com.yami.shop.bean.app.dto.CouponDto">-->
        <!--SELECT tc.*,tsd.`shop_name`-->
        <!--FROM tz_coupon tc-->
        <!--JOIN tz_shop_detail tsd-->
        <!--ON tsd.`shop_id` = tc.`shop_id`-->
        <!--WHERE-->
        <!--tc.suitable_prod_type =0 &#45;&#45; 获取全部商品券-->
          <!--&lt;!&ndash;AND tc.`stocks` >0&ndash;&gt;-->
          <!--AND tc.`overdue_status` =1 AND tc.`puton_status` = 1 and tsd.shop_status = 1-->
          <!--AND tc.`is_score_type` <![CDATA[<>]]> 1-->
        <!--ORDER BY tc.start_time DESC-->
    <!--</select>-->
    <select id="generalCouponList" resultType="com.yami.shop.bean.app.dto.CouponDto">
        SELECT c.*,cu.*
        FROM tz_coupon c
        LEFT JOIN
        (
            SELECT coupon_id, COUNT(*) cur_user_receive_count, SUM(IF(`status` = 1,1,0)) user_has_count  FROM tz_coupon_user
            WHERE user_id = #{userId}
            GROUP BY coupon_id
        ) AS cu ON cu.coupon_id = c.coupon_id
        WHERE c.shop_id = 0
        AND c.`overdue_status` =1 AND c.`puton_status` = 1
        AND c.`is_score_type` <![CDATA[<>]]> 1 AND IFNULL(c.`get_way`,0) <![CDATA[<>]]> 1
        ORDER BY c.coupon_id DESC
    </select>
    <select id="generalCouponListTourist" resultType="com.yami.shop.bean.app.dto.CouponDto">
        SELECT c.*
        FROM tz_coupon c
        WHERE c.shop_id = 0
          AND c.`overdue_status` =1 AND c.`puton_status` = 1
          AND c.`is_score_type` <![CDATA[<>]]> 1 AND IFNULL(c.`get_way`,0) <![CDATA[<>]]> 1
        ORDER BY c.coupon_id DESC
    </select>
    <select id="getCouponListByStatus" resultType="com.yami.shop.bean.app.dto.CouponDto">
        SELECT tc.*,tcu.*,sd.shop_name
        FROM tz_coupon_user tcu
        INNER JOIN tz_coupon tc
        ON tcu.`coupon_id` = tc.`coupon_id`
        LEFT JOIN tz_shop_detail sd
        ON tc.`shop_id` = sd.shop_id
        WHERE tcu.`user_id` = #{userId}
        AND tc.puton_status NOT IN (2,3)
        AND tcu.`status` = #{status}
        AND tcu.is_delete = 0
    </select>
         <!--AND tc.puton_status = 1-->
    <select id="getCouponListByShopIds" resultMap="couponOrderDtoMap">
      select tc.*,tcp.prod_id as prodIds,tcu.* from tz_coupon tc
      join tz_coupon_user tcu on tc.coupon_id = tcu.coupon_id
      left join tz_coupon_prod tcp on tcp.coupon_id = tc.coupon_id
      where tcu.user_id = #{userId}
          -- 获取用户未使用的优惠券
        AND tc.puton_status NOT IN (2,3)
        and tcu.status = 1
        and tcu.is_delete = 0
        and tc.shop_id = #{shopId}
    </select>
        <!--and tc.puton_status = 1-->
    <select id="listOverdueStatusShopIds" resultType="long">
        SELECT shop_id FROM tz_coupon
        WHERE end_time &lt; #{now}
        and valid_time_type = 1
        GROUP BY shop_id
    </select>
    <select id="listPutonCouponAndCouponProdsByShopId" resultMap="CouponAndCouponProdMap">
        SELECT c.*,cp.*,p.*
        FROM tz_coupon c
                 LEFT JOIN tz_coupon_prod cp ON c.coupon_id = cp.coupon_id
                 LEFT JOIN tz_prod p ON cp.prod_id = p.prod_id
        WHERE c.`overdue_status` = 1 AND c.puton_status =1 AND c.shop_id =#{shopId} AND c.`is_score_type` <![CDATA[<>]]> 1
        ORDER BY c.`start_time` DESC
    </select>
    <select id="listCouponIdsByUserId" resultType="com.yami.shop.bean.app.dto.CouponDto">
        SELECT tcu.coupon_id,tcu.`status`,COUNT(tcu.coupon_id) AS cur_user_receive_count
        FROM tz_coupon_user tcu
        LEFT JOIN tz_coupon tc
            ON tcu.`coupon_id` = tc.`coupon_id`
        WHERE tcu.`user_id` = #{userId}
          AND tcu.is_delete = 0
        GROUP BY tcu.coupon_id,tcu.`status`
    </select>
          <!--AND  tc.puton_status = 1-->
    <select id="getCouponCountByStatus" resultType="map">
      SELECT
      COUNT(CASE WHEN cu.`status` = 0 THEN 1 ELSE NULL END) AS 'expiredCount' ,-- 失效
      COUNT(CASE WHEN cu.`status` = 1 THEN 1 ELSE NULL END) AS 'unUseCount', -- 有效
      COUNT(CASE WHEN cu.`status` = 2 THEN 1 ELSE NULL END) AS 'useCount'  -- 过期
      FROM tz_coupon_user cu
      INNER JOIN tz_coupon c
      ON c.`coupon_id` = cu.`coupon_id` AND c.puton_status NOT IN (2,3)
      WHERE cu.`user_id` =#{userId}
      AND cu.`is_delete` = 0
    </select>
      <!--AND c.`puton_status` =1-->
    <select id="getPlatformPage" resultType="com.yami.shop.coupon.common.model.Coupon">
        SELECT c.*,sd.shop_name `shop_name`
        FROM tz_coupon c
        LEFT JOIN tz_shop_detail sd ON c.`shop_id` = sd.`shop_id`
        <where>
            <if test="coupon.shopId != null">
                AND c.shop_id = #{coupon.shopId}
            </if>
            <if test="coupon.shopId == null">
                AND c.shop_id != 0
            </if>
            <if test="coupon.couponName !=null">
                and trim(replace(c.coupon_name,' ','')) like trim(replace(concat('%',#{coupon.couponName},'%'),' ',''))
            </if>
            <if test="coupon.putonStatus != null">
                AND c.puton_status = #{coupon.putonStatus}
            </if>
            <if test="coupon.overdueStatus != null">
                AND c.overdue_status = #{coupon.overdueStatus}
            </if>
            <if test="coupon.endTime != null">
                AND c.end_time &lt;= #{coupon.endTime}
            </if>
            <if test="coupon.startTime != null">
                AND c.start_time &gt;= #{coupon.startTime}
            </if>
            <if test="coupon.couponType != null">
                AND c.coupon_type = #{coupon.couponType}
            </if>
            <if test="coupon.isScoreType != null">
                AND c.is_score_type = #{coupon.isScoreType}
            </if>
            <if test="coupon.shopName != null">
                and trim(replace(sd.shop_name,' ','')) like trim(replace(concat('%',#{coupon.shopName},'%'),' ',''))
            </if>
        </where>
        ORDER BY c.`coupon_id` DESC
    </select>
    <select id="getMultiShopPage" resultType="com.yami.shop.coupon.common.model.Coupon">
        SELECT c.*
        FROM tz_coupon c
        LEFT JOIN tz_shop_detail sd ON c.`shop_id` = sd.`shop_id`
        <where>
            <if test="coupon.shopId != null">
                AND c.shop_id = #{coupon.shopId}
            </if>
            <if test="coupon.couponName !=null">
                and trim(replace(c.coupon_name,' ','')) like trim(replace(concat('%',#{coupon.couponName},'%'),' ',''))
            </if>
            <if test="coupon.putonStatus != null">
                AND c.puton_status = #{coupon.putonStatus}
            </if>
            <if test="coupon.overdueStatus != null">
                AND c.overdue_status = #{coupon.overdueStatus}
            </if>
            <if test="coupon.endTime != null">
                AND c.end_time &lt;= #{coupon.endTime}
            </if>
            <if test="coupon.startTime != null">
                AND c.start_time &gt;= #{coupon.startTime}
            </if>
            <if test="coupon.couponType != null">
                AND c.coupon_type = #{coupon.couponType}
            </if>
        </where>
        ORDER BY c.`coupon_id` DESC
    </select>
    <select id="countTakeNum" resultType="java.lang.Integer">
        select COUNT(cu.coupon_user_id)
        from `tz_coupon_user` cu
        left join `tz_coupon` c on cu.coupon_id = c.coupon_id
        <where> cu.coupon_id = #{couponId}
            <if test="shopId != null">
                AND c.shop_id = #{shopId}
            </if>
        </where>
        GROUP BY cu.coupon_id
    </select>
    <select id="countUseNum" resultType="java.lang.Integer">
        select count(cur.coupon_use_record_id)
        from `tz_coupon_user` cu
        LEFT JOIN `tz_coupon_use_record` cur ON cur.coupon_user_id = cu.coupon_user_id
        where cu.coupon_id = #{couponId} and cur.`status`!=3
        group by cu.coupon_id
    </select>
    <update id="updatePutOnStatusByCouponId">
        UPDATE tz_coupon c SET c.`puton_status` =#{status} WHERE c.`coupon_id` = #{couponId}
    </update>
    <select id="getShopAvailableCouponIds" resultType="java.lang.Long">
        SELECT c.coupon_id FROM tz_coupon c
        LEFT JOIN tz_coupon_prod cp ON cp.`coupon_id` = c.`coupon_id`
        JOIN tz_prod p ON p.status = 1 AND p.prod_type &lt; 3 AND
        ((c.shop_id = p.shop_id AND c.suitable_prod_type=0) OR (p.prod_id = cp.prod_id  AND c.suitable_prod_type=1) OR (p.prod_id != cp.prod_id  AND c.suitable_prod_type=2 AND p.shop_id = c.shop_id))
        JOIN tz_shop_detail sd ON sd.shop_id = c.shop_id AND sd.shop_status = 1
        WHERE c.overdue_status = 1 AND c.puton_status = 1 AND c.is_score_type = 0 AND c.shop_id != 0
        GROUP BY c.coupon_id
        ORDER BY c.coupon_id DESC
        LIMIT #{adapter.begin}, #{adapter.size}
    </select>
    <update id="updateOverdueStatusByCouponId">
        UPDATE tz_coupon c SET c.`overdue_status` =#{overdueStatus} WHERE c.`coupon_id` = #{couponId}
    </update>
    <select id="countCouponPageByCouponDto" resultType="long">
        SELECT COUNT(DISTINCT c.coupon_id) FROM tz_coupon c
        LEFT JOIN tz_coupon_prod cp ON cp.`coupon_id` = c.`coupon_id`
        JOIN tz_prod p ON p.status = 1 AND p.prod_type &lt; 3 AND (
               (c.shop_id = p.shop_id AND c.suitable_prod_type=0) OR
               (p.prod_id = cp.prod_id  AND c.suitable_prod_type=1) OR
               (p.prod_id != cp.prod_id  AND c.suitable_prod_type=2 AND p.shop_id = c.shop_id)
        )
        JOIN tz_shop_detail sd ON sd.shop_id = c.shop_id AND sd.shop_status = 1
        WHERE c.overdue_status = 1 AND c.puton_status = 1 AND c.is_score_type = 0 AND c.shop_id != 0
    </select>
    <update id="updateCoupon">
        UPDATE tz_coupon
        <set>
            <if test="coupon.shopId != null">
                `shop_id` = #{coupon.shopId},
            </if>
            <if test="coupon.couponName != null">
                `coupon_name` = #{coupon.couponName},
            </if>
            <if test="coupon.couponName != null">
                `sub_title` = #{coupon.subTitle},
            </if>
            <if test="coupon.couponType != null">
                `coupon_type` = #{coupon.couponType},
            </if>
            <if test="coupon.cashCondition != null">
                `cash_condition` = #{coupon.cashCondition},
            </if>
            <if test="coupon.reduceAmount != null">
                `reduce_amount` = #{coupon.reduceAmount},
            </if>
            <if test="coupon.couponDiscount != null">
                `coupon_discount` = #{coupon.couponDiscount},
            </if>
            <if test="coupon.validTimeType != null">
                `valid_time_type` = #{coupon.validTimeType},
            </if>
            `launch_time` = #{coupon.launchTime},
            <if test="coupon.startTime != null">
                `start_time` = #{coupon.startTime},
            </if>
            <if test="coupon.endTime != null">
                `end_time` = #{coupon.endTime},
            </if>
            <if test="coupon.afterReceiveDays != null">
                `after_receive_days` = #{coupon.afterReceiveDays},
            </if>
            <if test="coupon.validDays != null">
                `valid_days` = #{coupon.validDays},
            </if>
            <if test="coupon.stocks != null">
                `stocks` = #{coupon.stocks},
            </if>
            <if test="coupon.sourceStock != null">
                `source_stock` = #{coupon.sourceStock},
            </if>
            <if test="coupon.suitableProdType != null">
                `suitable_prod_type` = #{coupon.suitableProdType},
            </if>
            <if test="coupon.limitNum != null">
                `limit_num` = #{coupon.limitNum},
            </if>
            <if test="coupon.version != null">
                `version` = #{coupon.version} + 1,
            </if>
            <if test="coupon.overdueStatus != null">
                `overdue_status` = #{coupon.overdueStatus},
            </if>
            <if test="coupon.putonStatus != null">
                `puton_status` = #{coupon.putonStatus},
            </if>
            <if test="coupon.getWay != null">
                `get_way` = #{coupon.getWay},
            </if>
        </set>
        WHERE coupon_id = #{coupon.couponId}
        <if test="coupon.version != null">
            and `version` = #{coupon.version}
        </if>
    </update>
</mapper>
yami-shop-coupon/yami-shop-coupon-common/src/main/resources/mapper/CouponProdMapper.xml
New file
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yami.shop.coupon.common.dao.CouponProdMapper">
    <resultMap id="BaseResultMap" type="com.yami.shop.coupon.common.model.CouponProd">
        <!--
          WARNING - @mbg.generated
        -->
        <id column="coupon_prod_id" jdbcType="BIGINT" property="couponProdId"/>
        <result column="coupon_id" jdbcType="BIGINT" property="couponId"/>
        <result column="prod_id" jdbcType="BIGINT" property="prodId"/>
    </resultMap>
    <delete id="deleteCouponProdsByCouponId">
    delete from tz_coupon_prod where coupon_id = #{couponId}
  </delete>
    <insert id="insertCouponProdsBatch">
        insert into tz_coupon_prod (coupon_id, prod_id) values
        <foreach collection="prodIds" item="prodId" separator=",">
            (#{couponId}, #{prodId})
        </foreach>
    </insert>
    <delete id="deleteCouponProdsByCouponIds">
        DELETE FROM tz_coupon_prod
        WHERE coupon_id IN
        <foreach collection="couponIds" item="couponId" separator="," open="(" close=")">
            #{couponId}
        </foreach>
    </delete>
</mapper>
yami-shop-coupon/yami-shop-coupon-common/src/main/resources/mapper/CouponUseRecordMapper.xml
New file
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yami.shop.coupon.common.dao.CouponUseRecordMapper">
    <resultMap id="couponUseMap" type="com.yami.shop.coupon.common.model.CouponUseRecord">
        <id property="couponUseRecordId" column="coupon_use_record_id"/>
        <!--<result property="couponId" column="coupon_id"/>-->
        <result property="couponUserId" column="coupon_user_id"/>
        <result property="orderNumber" column="order_number"/>
        <result property="userId" column="user_id"/>
        <result property="amount" column="amount"/>
        <result property="useTime" column="use_time"/>
    </resultMap>
    <resultMap id="couponUseRecordOrderMap" type="com.yami.shop.coupon.common.model.CouponUseRecord">
        <result column="coupon_use_record_id" property="couponUseRecordId"/>
        <result column="order_number" property="orderNumber"/>
        <result column="status" property="status"/>
        <collection property="couponUser" ofType="com.yami.shop.coupon.common.model.CouponUser">
            <id column="coupon_user_id" property="couponUserId"/>
            <result column="user_end_time" property="userEndTime"/>
            <collection property="coupon" ofType="com.yami.shop.coupon.common.model.Coupon">
                <id column="coupon_id" property="couponId"/>
                <result column="overdue_status" property="overdueStatus"/>
                <result column="puton_status" property="putonStatus"/>
            </collection>
        </collection>
    </resultMap>
    <insert id="addCouponUseRecode">
        INSERT INTO tz_coupon_use_record (coupon_user_id,user_id,order_number,amount,use_time,`status`) VALUES
        <foreach collection="couponUseRecordsList" item="couponUseRecord" separator=",">
            (#{couponUseRecord.couponUserId},#{couponUseRecord.userId},#{couponUseRecord.orderNumber},#{couponUseRecord.amount},#{couponUseRecord.useTime},#{couponUseRecord.status})
        </foreach>
    </insert>
    <update id="batchUpdateRecordByStatusAndOrderNums">
        <foreach collection="orderNumberList" item="orderNum" separator=";">
            UPDATE tz_coupon_use_record SET `status` = #{status}
            <where>
                order_number like CONCAT('%',#{orderNum},'%')
            </where>
        </foreach>
    </update>
    <select id="listByOrderNumber" resultMap="couponUseRecordOrderMap">
        SELECT cur.coupon_use_record_id,cu.coupon_user_id,cu.user_end_time,c.coupon_id,c.puton_status,c.overdue_status
        FROM tz_coupon_use_record cur
        JOIN tz_coupon_user cu ON cur.coupon_user_id = cu.coupon_user_id AND cu.status = 2
        JOIN tz_coupon c ON cu.coupon_id = c.coupon_id
        WHERE cur.order_number = #{orderNumber}
    </select>
    <select id="getOrderNumberContact" resultType="com.yami.shop.coupon.common.model.CouponUseRecord">
        SELECT coupon_use_record_id,order_number
        FROM tz_coupon_use_record cur
        WHERE order_number LIKE CONCAT('%',#{orderNumber},'%')
    </select>
    <update id="batchUpdateRecordStatusByStatusAndIds">
        <foreach collection="ids" item="id" separator=";">
            UPDATE tz_coupon_use_record SET `status` = #{status} WHERE coupon_use_record_id = #{id}
        </foreach>
    </update>
    <select id="listCouponUserIdsByOrderNumber" resultType="java.lang.Long">
        SELECT coupon_user_id
        FROM tz_coupon_use_record
        WHERE FIND_IN_SET(#{orderNumber}, order_number)
          and status = 0
    </select>
    <update id="unLockByIds">
        update tz_coupon_use_record
        set status = 3 where coupon_user_id in
        <foreach collection="couponUserIds" item="couponUserId" separator="," open="(" close=")">
            #{couponUserId}
        </foreach>
        and status = 1
    </update>
</mapper>
yami-shop-coupon/yami-shop-coupon-common/src/main/resources/mapper/CouponUserMapper.xml
New file
@@ -0,0 +1,246 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yami.shop.coupon.common.dao.CouponUserMapper">
    <resultMap id="BaseResultMap" type="com.yami.shop.coupon.common.model.CouponUser">
        <!--
          WARNING - @mbg.generated
        -->
        <result column="coupon_user_id" jdbcType="BIGINT" property="couponUserId"/>
        <result column="coupon_id" jdbcType="BIGINT" property="couponId"/>
        <result column="user_id" jdbcType="VARCHAR" property="userId"/>
        <result column="receive_time" jdbcType="TIMESTAMP" property="receiveTime"/>
        <result column="status" jdbcType="TINYINT" property="status"/>
        <result column="user_start_time" jdbcType="TIMESTAMP" property="userStartTime"/>
        <result column="user_end_time" jdbcType="TIMESTAMP" property="userEndTime"/>
        <result column="is_delete" jdbcType="TINYINT" property="isDelete"/>
    </resultMap>
    <resultMap id="CouponAndCouponUserMap" type="com.yami.shop.coupon.common.model.CouponUser">
        <result column="coupon_user_id" jdbcType="BIGINT" property="couponUserId"/>
        <result column="coupon_id" jdbcType="BIGINT" property="couponId"/>
        <result column="user_id" jdbcType="VARCHAR" property="userId"/>
        <result column="receive_time" jdbcType="TIMESTAMP" property="receiveTime"/>
        <result column="status" jdbcType="TINYINT" property="status"/>
        <result column="user_start_time" jdbcType="TIMESTAMP" property="userStartTime"/>
        <result column="user_end_time" jdbcType="TIMESTAMP" property="userEndTime"/>
        <association property="coupon" javaType="com.yami.shop.coupon.common.model.Coupon">
            <result column="coupon_id" jdbcType="BIGINT" property="couponId"/>
            <result column="shop_id" jdbcType="BIGINT" property="shopId"/>
            <result column="coupon_name" jdbcType="VARCHAR" property="couponName"/>
            <result column="sub_title" jdbcType="VARCHAR" property="subTitle"/>
            <result column="coupon_type" jdbcType="TINYINT" property="couponType"/>
            <result column="cash_condition" jdbcType="DECIMAL" property="cashCondition"/>
            <result column="reduce_amount" jdbcType="DECIMAL" property="reduceAmount"/>
            <result column="coupon_discount" jdbcType="DECIMAL" property="couponDiscount"/>
            <result column="valid_time_type" jdbcType="TINYINT" property="validTimeType"/>
            <result column="start_time" jdbcType="TIMESTAMP" property="startTime"/>
            <result column="end_time" jdbcType="TIMESTAMP" property="endTime"/>
            <result column="after_receive_days" jdbcType="INTEGER" property="afterReceiveDays"/>
            <result column="valid_days" jdbcType="INTEGER" property="validDays"/>
            <result column="stocks" jdbcType="INTEGER" property="stocks"/>
            <result column="suitable_prod_type" jdbcType="TINYINT" property="suitableProdType"/>
            <result column="limit_num" jdbcType="INTEGER" property="limitNum"/>
            <result column="version" jdbcType="INTEGER" property="version"/>
            <result column="overdue_status" jdbcType="TINYINT" property="overdueStatus"/>
            <result column="puton_status" jdbcType="TINYINT" property="putonStatus"/>
            <result column="shop_name" jdbcType="VARCHAR" property="shopName"/>
        </association>
    </resultMap>
    <select id="getCouponAndCouponUserByUserId" resultMap="CouponAndCouponUserMap">
        select cu.*,c.*,sd.shop_name from tz_coupon_user cu
        left join tz_coupon c on cu.coupon_id = c.coupon_id
        left join tz_shop_detail sd on c.shop_id = sd.shop_id
        where cu.user_id = #{userId} and (cu.status = 0 or cu.status = 1)
   </select>
    <select id="getCouponAndCouponUserByCouponUserIds" resultMap="CouponAndCouponUserMap">
        select cu.*,c.* from tz_coupon_user cu
        left join tz_coupon c on cu.coupon_id = c.coupon_id
        where cu.coupon_user_id in
        <foreach collection="couponUserIds" item="couponUserId" separator="," open="(" close=")">
            #{couponUserId}
        </foreach>
        and cu.status = 1 and c.overdue_status = 1 and c.puton_status = 1
    </select>
    <select id="getCouponAnalysisParamByDate" resultType="com.yami.shop.bean.param.CouponAnalysisParam">
        select c.coupon_name as couponName,c.coupon_type as couponType,
               COUNT(cu.coupon_user_id) as takeNum,
               cu.receive_time as currentDay,cu.coupon_id as couponId
        from `tz_coupon_user` cu
        left join `tz_coupon` c on cu.coupon_id = c.coupon_id
        <where>
            <if test="param.startTime != null and param.endTime != null">
                AND (cu.receive_time <![CDATA[ >= ]]> #{param.startTime} AND cu.receive_time <![CDATA[ <= ]]> #{param.endTime})
            </if>
            <if test="param.shopId != null">
                AND c.shop_id = #{param.shopId}
            </if>
        </where>
            GROUP BY cu.coupon_id
            order by cu.receive_time DESC
    </select>
    <select id="countUseNum" resultType="java.lang.Integer">
        select count(cur.coupon_use_record_id)
        from `tz_coupon_user` cu
        LEFT JOIN `tz_coupon_use_record` cur ON cur.coupon_user_id = cu.coupon_user_id
        <if test="param.startTime != null and param.endTime != null">
            AND (cur.use_time <![CDATA[ >= ]]> #{param.startTime} AND cur.use_time <![CDATA[ <= ]]> #{param.endTime})
        </if>
        where cu.coupon_id = #{couponId}
        group by cu.coupon_id
    </select>
    <select id="countTakeNum" resultType="java.lang.Integer">
        SELECT COUNT(coupon_user_id)
        FROM `tz_coupon_user` cu LEFT JOIN `tz_coupon` tc ON cu.coupon_id = tc.coupon_id
        <where>
            <if test="param.shopId != null">
                AND tc.shop_id = #{param.shopId}
            </if>
            <if test="param.startTime != null and param.endTime != null">
                AND (cu.receive_time <![CDATA[ >= ]]> #{param.startTime} AND cu.receive_time <![CDATA[ <= ]]> #{param.endTime})
            </if>
            <if test="couponId != null">
                AND cu.coupon_id = #{couponId}
            </if>
            <if test="status != null">
                AND cu.status = #{status}
            </if>
        </where>
    </select>
    <select id="countMemberGetCoupon" resultType="java.lang.Integer"
            parameterType="com.yami.shop.bean.param.CustomerReqParam">
        SELECT COUNT(DISTINCT(cu.user_id))
        FROM `tz_coupon_user` cu LEFT JOIN `tz_coupon` tc ON cu.coupon_id = tc.coupon_id
        LEFT JOIN `tz_user_extension` ue ON ue.user_id = cu.user_id
        <where>
            ue.level_type <![CDATA[ >= ]]> 0
            <if test="param.shopId != null">
                AND tc.shop_id = #{param.shopId}
            </if>
            <if test="param.startTime != null and param.endTime != null">
                AND (cu.receive_time <![CDATA[ >= ]]> #{param.startTime} AND cu.receive_time <![CDATA[ <= ]]> #{param.endTime})
            </if>
        </where>
    </select>
    <select id="countMemberCouponByParam" resultType="java.lang.Integer"
            parameterType="com.yami.shop.bean.param.MemberReqParam">
        SELECT COUNT(DISTINCT(cu.user_id))
        FROM `tz_coupon_user` cu LEFT JOIN `tz_coupon` tc ON cu.coupon_id = tc.coupon_id
        LEFT JOIN `tz_user_extension` ue ON ue.user_id = cu.user_id
        <where>
            <choose>
                <when test="param.memberType == 1">
                    AND ue.level_type = 0
                </when>
                <when test="param.memberType == 2">
                    AND ue.level_type = 1
                </when>
            </choose>
            <if test="param.shopId != null">
                AND tc.shop_id = #{param.shopId}
            </if>
            <if test="param.startTime != null and param.endTime != null">
                AND (cu.receive_time <![CDATA[ >= ]]> #{param.startTime} AND cu.receive_time <![CDATA[ <= ]]> #{param.endTime})
            </if>
        </where>
    </select>
    <select id="countCouponUsedNums" resultType="java.lang.Integer" parameterType="java.lang.String">
        SELECT COUNT(1) FROM `tz_coupon_user` cu
        WHERE cu.status = 2 AND cu.user_id = #{userId} AND cu.is_delete = 0
    </select>
    <select id="countCouponExpiredNums" resultType="java.lang.Integer" parameterType="java.lang.String">
        SELECT COUNT(1) FROM `tz_coupon_user` cu
        WHERE cu.status = 0 AND cu.user_id = #{userId} AND cu.is_delete = 0
    </select>
    <select id="countCouponUsableNums" resultType="java.lang.Integer">
         SELECT COUNT(1) FROM `tz_coupon_user` cu
        WHERE cu.user_id = #{userId} AND cu.is_delete = 0
        AND cu.status = 1
    </select>
    <select id="getPageByUserId" resultMap="CouponAndCouponUserMap">
        SELECT
        cu.coupon_user_id,
        c.coupon_name,
        c.coupon_type,
        cu.user_start_time,
        cu.user_end_time,
        cu.status,
        c.cash_condition,
        c.reduce_amount,
        c.coupon_discount,
        cu.receive_time
        FROM `tz_coupon_user` cu
        LEFT JOIN `tz_coupon` c ON c.coupon_id = cu.coupon_id
        <where>
            cu.user_id = #{userId} AND cu.is_delete = 0
            <if test="status != null">
                AND cu.status = #{status}
            </if>
        </where>
        ORDER BY cu.receive_time DESC
    </select>
    <delete id="deleteUnValidTimeCoupons">
    delete from tz_coupon_user where user_end_time &lt; #{date} and status = 0
     </delete>
    <update id="updateStatusByTime">
    update tz_coupon_user set status = 0 where user_end_time &lt; #{now}
   </update>
    <update id="deleteUserCoupon">
        UPDATE tz_coupon_user cu SET cu.is_delete =1 WHERE cu.user_id =#{userId} AND cu.coupon_id = #{couponId}
    </update>
    <update id="updateUseStatusByCouponUserId">
        UPDATE tz_coupon_user SET `status` = #{status} WHERE coupon_user_id = #{couponUserId}
    </update>
    <update id="batchUpdateUserCouponStatus">
        UPDATE tz_coupon_user SET `status` = #{status}
        WHERE coupon_user_id IN
        <foreach collection="couponUserIds" item="userCouponId" open="(" close=")" separator=",">
            #{userCouponId}
        </foreach>
    </update>
    <update id="updateStatusByOrderNumber">
        UPDATE tz_coupon_user SET `status` = #{status}
        WHERE order_number = #{orderNumber}
    </update>
    <select id="countNormalByCouponUserId" resultType="int">
        select ifnull(count(*),0) from tz_coupon tc
        join tz_coupon_user tcu on tc.coupon_id = tcu.coupon_id
        left join tz_coupon_prod tcp on tcp.coupon_id = tc.coupon_id
        where tcu.user_id = #{userId}
        -- 获取用户未使用的优惠券
        and tc.puton_status NOT IN (2,3)
        and tcu.status = 1
        and tcu.is_delete = 0
        and tcu.coupon_user_id in
        <foreach collection="couponUserIds" item="couponUserId" separator="," open="(" close=")">
            #{couponUserId}
        </foreach>
    </select>
    <select id="listByCouponIdsAndUserId" resultType="com.yami.shop.coupon.common.model.CouponUser">
        SELECT coupon_id, COUNT(*) cur_user_receive_count FROM tz_coupon_user
        WHERE `status` = 1 AND user_id =  #{userId}
        GROUP BY coupon_id
    </select>
    <select id="getCouponCountInfo" resultType="com.yami.shop.bean.param.CouponUserParam">
        SELECT
        IFNULL(SUM(IF(cu.`status` = 0, 1, 0)), 0) couponExpiredNums,
        IFNULL(SUM(IF(cu.`status` = 1, 1, 0)), 0) couponUsableNums,
        IFNULL(SUM(IF(cu.`status` = 2, 1, 0)), 0) couponUsedNums
        FROM `tz_coupon_user` cu
        LEFT JOIN `tz_coupon` c ON cu.coupon_id = c.coupon_id
        <if test="shopId != null">
            AND c.shop_id = #{shopId}
        </if>
        WHERE cu.user_id = #{userId} AND cu.is_delete = 0
    </select>
</mapper>
yami-shop-coupon/yami-shop-coupon-multishop/pom.xml
New file
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>yami-shop-coupon</artifactId>
        <groupId>com.yami.shop</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>yami-shop-coupon-multishop</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-coupon-common</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-security-multishop</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
    </dependencies>
</project>
yami-shop-coupon/yami-shop-coupon-multishop/src/main/java/com/yami/shop/coupon/multishop/config/SwaggerConfiguration.java
New file
@@ -0,0 +1,38 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.multishop.config;
import lombok.AllArgsConstructor;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * 优惠券
 * @author lanhai
 */
@Configuration("couponSwaggerConfiguration")
@AllArgsConstructor
public class SwaggerConfiguration {
    @Bean
    public GroupedOpenApi couponRestApi() {
        return GroupedOpenApi.builder()
                .group("优惠券接口")
                .packagesToScan("com.yami.shop.coupon.multishop.controller")
                .pathsToMatch("/**")
                .build();
    }
}
yami-shop-coupon/yami-shop-coupon-multishop/src/main/java/com/yami/shop/coupon/multishop/controller/CouponController.java
New file
@@ -0,0 +1,206 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.multishop.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.enums.OfflineHandleEventType;
import com.yami.shop.bean.model.OfflineHandleEvent;
import com.yami.shop.bean.param.OfflineHandleEventAuditParam;
import com.yami.shop.bean.param.SendUserCouponsParam;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.coupon.common.constants.CouponStatusEnum;
import com.yami.shop.coupon.common.constants.ValidTimeTypeEnum;
import com.yami.shop.coupon.common.model.Coupon;
import com.yami.shop.coupon.common.param.UserCouponParam;
import com.yami.shop.coupon.common.service.CouponService;
import com.yami.shop.security.common.enums.SysTypeEnum;
import com.yami.shop.security.multishop.util.SecurityUtils;
import com.yami.shop.service.OfflineHandleEventService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import org.apache.commons.collections4.CollectionUtils;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
 * @author lgh on 2018/12/27.
 */
@RestController("adminCouponController")
@RequestMapping("/admin/coupon")
@Tag(name = "商家端优惠券接口")
public class CouponController {
    @Autowired
    private CouponService couponService;
    @Autowired
    private OfflineHandleEventService offlineHandleEventService;
    @GetMapping("/page")
    @PreAuthorize("@pms.hasPermission('admin:coupon:page')")
    @Operation(summary = "分页获取优惠券列表信息")
    public ServerResponseEntity<IPage<Coupon>> page(@ParameterObject Coupon coupon, PageParam<Coupon> page) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        coupon.setShopId(shopId);
        IPage<Coupon> multiShopPage = couponService.getMultiShopPage(page, coupon);
        return ServerResponseEntity.success(multiShopPage);
    }
    @GetMapping("/info/{id}")
    @Operation(summary = "根据优惠券id获取优惠券信息")
    @Parameter(name = "id", description = "优惠券id" )
    public ServerResponseEntity<Coupon> info(@PathVariable("id") Long id) {
        Coupon coupon = couponService.getCouponAndCouponProdsByCouponId(id);
        if (!Objects.equals(SecurityUtils.getShopUser().getShopId(), coupon.getShopId())) {
            throw new YamiShopBindException("yami.no.auth");
        }
        return ServerResponseEntity.success(coupon);
    }
    @PostMapping
    @PreAuthorize("@pms.hasPermission('admin:coupon:save')")
    @Operation(summary = "新增优惠券")
    public ServerResponseEntity<Long> save(@RequestBody @Valid Coupon coupon) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        coupon.setShopId(shopId);
        coupon.setSourceStock(coupon.getStocks());
        //判断为领取后生效类型时,开始时间和结束时间为空
        if (Objects.equals(coupon.getValidTimeType(), ValidTimeTypeEnum.RECEIVE.getValue())) {
            coupon.setEndTime(null);
            coupon.setStartTime(null);
        }
        couponService.insertCouponAndCouponProds(coupon);
        return ServerResponseEntity.success(coupon.getCouponId());
    }
    @PutMapping
    @PreAuthorize("@pms.hasPermission('admin:coupon:update')")
    @Operation(summary = "修改优惠券")
    public ServerResponseEntity<Void> update(@RequestBody @Valid Coupon coupon) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        Coupon dbCoupon = couponService.getById(coupon.getCouponId());
        if (!Objects.equals(dbCoupon.getShopId(), shopId)) {
            // 没有权限修改该优惠券信息
            throw new YamiShopBindException("yami.coupon.no.auth");
        }
        if (Objects.equals(dbCoupon.getPutonStatus(), CouponStatusEnum.OFFLINE.getValue()) || Objects.equals(dbCoupon.getPutonStatus(), CouponStatusEnum.WAIT_AUDIT.getValue())) {
            // 优惠券处于违规下线或者待审核状态时,商家不能直接修改优惠券状态
            coupon.setPutonStatus(dbCoupon.getPutonStatus());
        } else if (Objects.equals(coupon.getPutonStatus(), CouponStatusEnum.OFFLINE.getValue()) || Objects.equals(coupon.getPutonStatus(), CouponStatusEnum.WAIT_AUDIT.getValue())) {
            // 当数据库中的优惠券状态不是违规下线或者待审核状态时,如果接口传进来的优惠券状态为违规下线或者待审核状态,说明该优惠券应该已经被审核了
            // 使用数据库的优惠券状态
            coupon.setPutonStatus(dbCoupon.getPutonStatus());
        }
        coupon.setShopId(shopId);
        //被领取数量
        int receNum = dbCoupon.getSourceStock() - dbCoupon.getStocks();
        //新的原始库存
        int newSourceStock = coupon.getStocks() + receNum;
        coupon.setSourceStock(newSourceStock);
        couponService.updateCouponAndCouponProds(coupon);
        return ServerResponseEntity.success();
    }
    @DeleteMapping
    @PreAuthorize("@pms.hasPermission('admin:coupon:delete')")
    @Operation(summary = "删除优惠券")
    public ServerResponseEntity<Void> delete(@RequestBody Long couponId) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        Coupon dbCoupon = couponService.getById(couponId);
        if (!Objects.equals(dbCoupon.getShopId(), shopId)) {
            // 没有权限修改该优惠券信息
            throw new YamiShopBindException("yami.coupon.no.auth");
        }
        couponService.deleteByCouponId(couponId);
        return ServerResponseEntity.success();
    }
    @GetMapping("/getOfflineHandleEventByCouponId/{couponId}")
    @Operation(summary = "通过优惠券id获取下线信息")
    @Parameter(name = "couponId", description = "优惠券id" )
    public ServerResponseEntity<OfflineHandleEvent> getOfflineHandleEventByDiscountId(@PathVariable("couponId") Long couponId) {
        OfflineHandleEvent offlineHandleEvent = offlineHandleEventService.getProcessingEventByHandleTypeAndHandleId(OfflineHandleEventType.COUPON.getValue(), couponId);
        return ServerResponseEntity.success(offlineHandleEvent);
    }
    @PostMapping("/auditApply")
    @PreAuthorize("@pms.hasPermission('admin:coupon:auditApply')")
    @Operation(summary = "违规商品提交审核")
    public ServerResponseEntity<Void> auditApply(@RequestBody OfflineHandleEventAuditParam offlineHandleEventAuditParam) {
        Coupon coupon = couponService.getCouponAndCouponProdsByCouponId(offlineHandleEventAuditParam.getHandleId());
        if (coupon == null) {
            // 未找到该活动信息
            throw new YamiShopBindException("yami.activity.cannot.find");
        }
        couponService.auditApply(offlineHandleEventAuditParam.getEventId(), offlineHandleEventAuditParam.getHandleId(), offlineHandleEventAuditParam.getReapplyReason());
        // 移除缓存
        couponService.removeCouponAndCouponProdsCache(coupon.getShopId());
        return ServerResponseEntity.success();
    }
    @GetMapping("/listCanSendCoupon")
    @Operation(summary = "获取品牌可以发放给会员的优惠券列表")
    public ServerResponseEntity<IPage<Coupon>> listCanSendCoupon(PageParam<Coupon> page, @ParameterObject Coupon coupon) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        PageParam<Coupon> couponList  = couponService.page(page, new LambdaQueryWrapper<Coupon>()
                .eq(Coupon::getShopId, shopId)
                .eq(Coupon::getPutonStatus, 1)
                .eq(Coupon::getGetWay, 1)
                .like(StrUtil.isNotBlank(coupon.getCouponName()), Coupon::getCouponName, coupon.getCouponName())
                .orderByDesc(Coupon::getCouponId));;
        return ServerResponseEntity.success(couponList);
    }
    @PutMapping("/sendUserCoupon")
    @Operation(summary = "品牌批量发放优惠券给会员")
    @PreAuthorize("@pms.hasPermission('admin:coupon:send')")
    public ServerResponseEntity<Boolean> sendUserCoupon(@RequestBody UserCouponParam param) {
//        if (!Objects.equals(SecurityUtils.getShopUser().getSysType(), SysTypeEnum.BRAND.value())) {
//            // 没有权限修改该优惠券信息
//            throw new YamiShopBindException("yami.coupon.no.auth");
//        }
        Long shopId = SecurityUtils.getShopUser().getShopId();
        List<String> userIds = param.getUserIds();
        if (CollectionUtils.isEmpty(userIds)) {
            return ServerResponseEntity.success();
        }
        List<SendUserCouponsParam> coupons = param.getCoupons();
        if (CollectionUtils.isEmpty(coupons)) {
            return ServerResponseEntity.success();
        }
        for (String userId : userIds) {
            for (SendUserCouponsParam coupon : coupons) {
                Long couponId = coupon.getCouponId();
                Integer nums = coupon.getNums();
                if (Objects.equals(0, nums)) {
                    continue;
                }
                for (int i = 0; i < nums; i++) {
                    couponService.batchBindCouponByIds(Collections.singletonList(couponId), userId, shopId);
//                    couponService.deleteCache(shopId, null);
                }
            }
        }
        return ServerResponseEntity.success();
    }
}
yami-shop-coupon/yami-shop-coupon-multishop/src/main/java/com/yami/shop/coupon/multishop/controller/CouponProdController.java
New file
@@ -0,0 +1,75 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.multishop.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.coupon.common.model.CouponProd;
import com.yami.shop.coupon.common.service.CouponProdService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
 * @author lgh on 2018/12/27.
 */
@RestController
@RequestMapping("/admin/couponProd")
@Tag(name = "商家端优惠券商品接口")
public class CouponProdController {
    @Autowired
    private CouponProdService couponProdService;
    @GetMapping("/page")
    @Operation(summary = "分页获取优惠券商品")
    public ServerResponseEntity<IPage<CouponProd>> page(@ParameterObject CouponProd couponProd, PageParam<CouponProd> page) {
        IPage<CouponProd> couponProds = couponProdService.page(page, new LambdaQueryWrapper<CouponProd>());
        return ServerResponseEntity.success(couponProds);
    }
    @GetMapping("/info/{id}")
    @Operation(summary = "根据优惠券商品id获取信息")
    @Parameter(name = "id", description = "优惠券商品id" )
    public ServerResponseEntity<CouponProd> info(@PathVariable("id") Long id) {
        CouponProd couponProd = couponProdService.getById(id);
        return ServerResponseEntity.success(couponProd);
    }
    @PostMapping
    @Operation(summary = "保存优惠券商品信息")
    public ServerResponseEntity<Void> save(@RequestBody @Valid CouponProd couponProd) {
        couponProdService.save(couponProd);
        return ServerResponseEntity.success();
    }
    @PutMapping
    @Operation(summary = "修改优惠券商品信息")
    public ServerResponseEntity<Void> update(@RequestBody @Valid CouponProd couponProd) {
        couponProdService.updateById(couponProd);
        return ServerResponseEntity.success();
    }
    @DeleteMapping("/{id}")
    @Operation(summary = "根据id删除优惠券商品")
    @Parameter(name = "id", description = "优惠券商品id" )
    public ServerResponseEntity<Void> delete(@PathVariable Long id) {
        couponProdService.removeById(id);
        return ServerResponseEntity.success();
    }
}
yami-shop-coupon/yami-shop-coupon-multishop/src/main/java/com/yami/shop/coupon/multishop/controller/CouponUserController.java
New file
@@ -0,0 +1,75 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.multishop.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.coupon.common.model.CouponUser;
import com.yami.shop.coupon.common.service.CouponUserService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
 * @author lgh on 2018/12/27.
 */
@RestController
@RequestMapping("/admin/couponUser")
@Tag(name = "商家端优惠券用户接口")
public class CouponUserController {
    @Autowired
    private CouponUserService couponUserService;
    @GetMapping("/page")
    @Operation(summary = "分页获取优惠券用户信息")
    public ServerResponseEntity<IPage<CouponUser>> page(@ParameterObject CouponUser couponUser, PageParam<CouponUser> page) {
        IPage<CouponUser> couponUsers = couponUserService.page(page, new LambdaQueryWrapper<CouponUser>());
        return ServerResponseEntity.success(couponUsers);
    }
    @GetMapping("/info/{id}")
    @Operation(summary = "根据优惠券用户id获取信息")
    @Parameter(name = "id", description = "优惠券用户id" )
    public ServerResponseEntity<CouponUser> info(@PathVariable("id") Long id) {
        CouponUser couponUser = couponUserService.getById(id);
        return ServerResponseEntity.success(couponUser);
    }
    @PostMapping
    @Operation(summary = "新增优惠券用户")
    public ServerResponseEntity<Void> save(@RequestBody @Valid CouponUser couponUser) {
        couponUserService.save(couponUser);
        return ServerResponseEntity.success();
    }
    @PutMapping
    @Operation(summary = "修改优惠券用户")
    public ServerResponseEntity<Void> update(@RequestBody @Valid CouponUser couponUser) {
        couponUserService.updateById(couponUser);
        return ServerResponseEntity.success();
    }
    @DeleteMapping("/{id}")
    @Operation(summary = "根据优惠券用户id删除信息")
    @Parameter(name = "id", description = "优惠券用户id" )
    public ServerResponseEntity<Void> delete(@PathVariable Long id) {
        couponUserService.removeById(id);
        return ServerResponseEntity.success();
    }
}
yami-shop-coupon/yami-shop-coupon-platform/pom.xml
New file
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>yami-shop-coupon</artifactId>
        <groupId>com.yami.shop</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>yami-shop-coupon-platform</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-coupon-common</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-security-platform</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
    </dependencies>
</project>
yami-shop-coupon/yami-shop-coupon-platform/src/main/java/com/yami/shop/coupon/platform/config/SwaggerConfiguration.java
New file
@@ -0,0 +1,36 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.platform.config;
import lombok.AllArgsConstructor;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * 优惠券
 * @author lanhai
 */
@Configuration("couponSwaggerConfiguration")
@AllArgsConstructor
public class SwaggerConfiguration {
    @Bean
    public GroupedOpenApi couponRestApi() {
        return GroupedOpenApi.builder()
                .group("优惠券接口")
                .packagesToScan("com.yami.shop.coupon.platform.controller")
                .pathsToMatch("/**")
                .build();
    }
}
yami-shop-coupon/yami-shop-coupon-platform/src/main/java/com/yami/shop/coupon/platform/controller/CouponController.java
New file
@@ -0,0 +1,268 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.platform.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.enums.OfflineHandleEventType;
import com.yami.shop.bean.enums.SendType;
import com.yami.shop.bean.event.SendMessageEvent;
import com.yami.shop.bean.model.OfflineHandleEvent;
import com.yami.shop.bean.param.NotifyTemplateParam;
import com.yami.shop.bean.param.OfflineHandleEventAuditParam;
import com.yami.shop.bean.param.SendUserCouponsParam;
import com.yami.shop.bean.param.UserUpdateParam;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.coupon.common.model.Coupon;
import com.yami.shop.coupon.common.model.CouponUser;
import com.yami.shop.coupon.common.service.CouponService;
import com.yami.shop.coupon.common.service.CouponUserService;
import com.yami.shop.security.platform.util.SecurityUtils;
import com.yami.shop.service.OfflineHandleEventService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.Operation;
import org.apache.commons.collections4.CollectionUtils;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
 * 优惠券后台接口
 *
 * @author lanhai
 */
@RestController("adminCouponController")
@RequestMapping("/platform/coupon")
@Tag(name = "平台端优惠券接口")
public class CouponController {
    @Autowired
    private CouponService couponService;
    @Autowired
    private CouponUserService couponUserService;
    @Autowired
    private OfflineHandleEventService offlineHandleEventService;
    @Autowired
    private  ApplicationEventPublisher eventPublisher;
    @GetMapping("/page")
    @PreAuthorize("@pms.hasPermission('platform:coupon:page')")
    @Operation(summary = "分页获取优惠券列表信息")
    public ServerResponseEntity<IPage<Coupon>> page(@ParameterObject Coupon coupon, PageParam<Coupon> page) {
        IPage<Coupon> couponPage = couponService.getPlatformPage(page, coupon);
        return ServerResponseEntity.success(couponPage);
    }
    @GetMapping("/list")
    @Operation(summary = "获取优惠券列表信息")
    public ServerResponseEntity<IPage<Coupon>> couponList(PageParam<Coupon> page, @ParameterObject Coupon coupon) {
        PageParam<Coupon> couponPage = couponService.page(page, new LambdaQueryWrapper<Coupon>()
                .eq(Coupon::getShopId, Constant.PLATFORM_SHOP_ID)
                .eq(Coupon::getPutonStatus, 1)
                .eq(Objects.nonNull(coupon.getGetWay()), Coupon::getGetWay, coupon.getGetWay())
                .like(StrUtil.isNotBlank(coupon.getCouponName()), Coupon::getCouponName, coupon.getCouponName())
                .orderByDesc(Coupon::getCouponId)
        );
        return ServerResponseEntity.success(couponPage);
    }
    @GetMapping("/pageByPlatform")
    @PreAuthorize("@pms.hasPermission('platform:coupon:page')")
    @Operation(summary = "分页获取平台优惠券")
    public ServerResponseEntity<IPage<Coupon>> pageByPlatform(@ParameterObject Coupon coupon, PageParam<Coupon> page) {
        coupon.setShopId(Constant.PLATFORM_SHOP_ID);
        IPage<Coupon> couponPage = couponService.getPlatformPage(page, coupon);
        return ServerResponseEntity.success(couponPage);
    }
    @PutMapping("/removeScore")
    @PreAuthorize("@pms.hasPermission('platform:coupon:delete')")
    @Operation(summary = "修改优惠券不为积分商品")
    @Parameter(name = "couponId", description = "优惠券id" , required = true)
    public ServerResponseEntity<IPage<Coupon>> removeScore(@RequestBody Long couponId) {
        Coupon coupon = couponService.getById(couponId);
        coupon.setIsScoreType(0);
        coupon.setScorePrice(0);
        couponService.updateById(coupon);
        return ServerResponseEntity.success();
    }
    @PutMapping("/couponByScore")
    @PreAuthorize("@pms.hasPermission('platform:coupon:update')")
    @Operation(summary = "修改平台券可以积分兑换")
    public ServerResponseEntity<IPage<Coupon>> couponByScore(@RequestBody @Valid Coupon coupon) {
        if (coupon.getScorePrice() == null) {
            // 请输入正确的积分数量
            throw new YamiShopBindException("yami.user.score.input.check");
        }
        coupon.setIsScoreType(1);
        couponService.updateById(coupon);
        return ServerResponseEntity.success();
    }
    @GetMapping("/scorePage")
    @PreAuthorize("@pms.hasPermission('platform:coupon:page')")
    @Operation(summary = "分页获取积分可换优惠券")
    public ServerResponseEntity<IPage<Coupon>> pageByScore(@ParameterObject Coupon coupon, PageParam<Coupon> page) {
        coupon.setIsScoreType(1);
        IPage<Coupon> couponPage = couponService.getPlatformPage(page, coupon);
        return ServerResponseEntity.success(couponPage);
    }
    @GetMapping("/info/{id}")
    @PreAuthorize("@pms.hasPermission('platform:coupon:info')")
    @Operation(summary = "根据优惠券id获取优惠券信息")
    @Parameter(name = "id", description = "优惠券id" , required = true)
    public ServerResponseEntity<Coupon> info(@PathVariable("id") Long id) {
        Coupon coupon = couponService.getCouponAndCouponProdsByCouponId(id);
        return ServerResponseEntity.success(coupon);
    }
    @DeleteMapping
    @PreAuthorize("@pms.hasPermission('platform:coupon:delete')")
    @Operation(summary = "根据优惠券id删除优惠券")
    @Parameter(name = "couponId", description = "优惠券id" , required = true)
    public ServerResponseEntity<Void> delete(@RequestBody Long couponId) {
        couponService.deleteByCouponId(couponId);
        return ServerResponseEntity.success();
    }
    @GetMapping("/getOfflineHandleEventByCouponId/{couponId}")
    @PreAuthorize("@pms.hasPermission('platform:coupon:info')")
    @Operation(summary = "通过优惠券id获取下线信息")
    @Parameter(name = "couponId", description = "优惠券id" , required = true)
    public ServerResponseEntity<OfflineHandleEvent> getOfflineHandleEventByCouponId(@PathVariable("couponId") Long couponId) {
        OfflineHandleEvent offlineHandleEvent = offlineHandleEventService.getProcessingEventByHandleTypeAndHandleId(OfflineHandleEventType.COUPON.getValue(), couponId);
        return ServerResponseEntity.success(offlineHandleEvent);
    }
    @PostMapping("/offline")
    @PreAuthorize("@pms.hasPermission('platform:coupon:update')")
    @Operation(summary = "下线活动")
    public ServerResponseEntity<Void> offline(@RequestBody OfflineHandleEvent offlineHandleEvent) {
        Long sysUserId = SecurityUtils.getSysUser().getUserId();
        Coupon coupon = couponService.getCouponAndCouponProdsByCouponId(offlineHandleEvent.getHandleId());
        if (coupon == null) {
            // 未找到该活动信息
            throw new YamiShopBindException("yami.activity.cannot.find");
        }
        couponService.offline(coupon, offlineHandleEvent.getOfflineReason(), sysUserId);
        //发送活动下架提醒给商家
        NotifyTemplateParam shopParam = new NotifyTemplateParam();
        shopParam.setShopId(coupon.getShopId());
        shopParam.setActivityId(coupon.getCouponId());
        shopParam.setActivityName(coupon.getCouponName());
        shopParam.setSendType(SendType.ACTIVITY_OFFLINE.getValue());
        eventPublisher.publishEvent(new SendMessageEvent(shopParam));
        return ServerResponseEntity.success();
    }
    @PostMapping("/auditCoupon")
    @PreAuthorize("@pms.hasPermission('platform:coupon:update')")
    @Operation(summary = "审核活动")
    public ServerResponseEntity<Void> auditCoupon(@RequestBody OfflineHandleEventAuditParam offlineHandleEventAuditParam) {
        Long sysUserId = SecurityUtils.getSysUser().getUserId();
        Coupon coupon = couponService.getCouponAndCouponProdsByCouponId(offlineHandleEventAuditParam.getHandleId());
        if (coupon == null) {
            // 未找到该活动信息
            throw new YamiShopBindException("yami.activity.cannot.find");
        }
        couponService.auditCoupon(offlineHandleEventAuditParam, sysUserId);
        //发送活动审核提醒给商家
        NotifyTemplateParam shopParam = new NotifyTemplateParam();
        shopParam.setShopId(coupon.getShopId());
        shopParam.setActivityId(coupon.getCouponId());
        shopParam.setActivityName(coupon.getCouponName());
        shopParam.setSendType(SendType.ACTIVITY_AUDIT.getValue());
        eventPublisher.publishEvent(new SendMessageEvent(shopParam));
        // 移除缓存
        couponService.removeCouponAndCouponProdsCache(coupon.getShopId());
        return ServerResponseEntity.success();
    }
    @PostMapping
    @Operation(summary = "保存优惠券")
    public ServerResponseEntity<Long> save(@RequestBody @Valid Coupon coupon) {
        // 此处新增优惠券皆为平台通用
        coupon.setShopId(Constant.PLATFORM_SHOP_ID);
        coupon.setSourceStock(coupon.getStocks());
        couponService.insertCouponAndCouponProds(coupon);
        return ServerResponseEntity.success(coupon.getCouponId());
    }
    @PutMapping
    @Operation(summary = "修改优惠券")
    public ServerResponseEntity<Void> update(@RequestBody @Valid Coupon coupon) {
        // 查询平台下优惠券
        Coupon dbCoupon = couponService.getById(coupon.getCouponId());
        if (null == dbCoupon) {
            // 优惠券不存在
            throw new YamiShopBindException("yami.coupon.no.exist");
        }
        coupon.setShopId(dbCoupon.getShopId());
        //被领取数量
        int receNum = dbCoupon.getSourceStock() - dbCoupon.getStocks();
        //新的原始库存
        int newSourceStock = coupon.getStocks() + receNum;
        coupon.setSourceStock(newSourceStock);
        couponService.updateCouponAndCouponProds(coupon);
        return ServerResponseEntity.success();
    }
    @PutMapping("/sendUserCoupon")
    @PreAuthorize("@pms.hasPermission('platform:coupon:sendUserCoupon')")
    @Operation(summary = "平台批量发放优惠券给会员")
    public ServerResponseEntity<Boolean> sendUserCoupon(@RequestBody UserUpdateParam param) {
        List<String> userIds = param.getUserIds();
        if (CollectionUtils.isEmpty(userIds)) {
            return ServerResponseEntity.success();
        }
        List<SendUserCouponsParam> coupons = param.getCoupons();
        if (CollectionUtils.isEmpty(coupons)) {
            return ServerResponseEntity.success();
        }
        for (String userId : userIds) {
            for (SendUserCouponsParam coupon : coupons) {
                Long couponId = coupon.getCouponId();
                Integer nums = coupon.getNums();
                if (Objects.equals(0, nums)) {
                    continue;
                }
                couponService.bindCouponById(couponId, userId, nums, Constant.PLATFORM_SHOP_ID);
            }
        }
        return ServerResponseEntity.success();
    }
    @GetMapping("/pageByUserId")
    @Operation(summary = "获取某个用户的优惠券明细")
    @Parameters({
            @Parameter(name = "userId", description = "用户id" ),
            @Parameter(name = "status", description = "优惠券状态 0:失效 1:有效 2:使用过" )
    })
    public ServerResponseEntity<IPage<CouponUser>> getPageByUserId(PageParam<CouponUser> page, String userId, Integer status) {
        IPage<CouponUser> resPage = couponService.getPageByUserId(page, userId, status);
        return ServerResponseEntity.success(resPage);
    }
}
yami-shop-coupon/yami-shop-coupon-platform/src/main/java/com/yami/shop/coupon/platform/task/CouponTask.java
New file
@@ -0,0 +1,94 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.coupon.platform.task;
import cn.hutool.core.date.DateUtil;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.yami.shop.common.util.CacheManagerUtil;
import com.yami.shop.coupon.common.dao.CouponMapper;
import com.yami.shop.coupon.common.service.CouponService;
import com.yami.shop.coupon.common.service.CouponUserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
/**
 * 优惠券定时任务
 * //0 0 0/1 * * ?
 * @author lanhai
 */
@Slf4j
@AllArgsConstructor
@Component
public class CouponTask {
    private final CouponUserService couponUserService;
    private final CouponService couponService;
    private final CouponMapper couponMapper;
    private final CacheManagerUtil cacheManagerUtil;
    /**
     * 删除用户失效30天以上的优惠券
     */
    @XxlJob("deleteCouponUser")
    public void deleteCouponUser() {
        log.info("删除用户失效180天以上的优惠券");
        // 删除用户失效半年以上的优惠券 参考京东
        couponUserService.deleteUnValidTimeCoupons(DateUtil.offsetDay(new Date(), -180));
    }
    /**
     * 改变用户优惠券的状态(设为失效状态)
     */
    @XxlJob("changeCouponUser")
    public void changeCouponUser() {
        Date now = new Date();
        log.info("设置用户的过期优惠券为失效状态");
        // 设置用户的过期优惠券为失效状态
        couponUserService.updateStatusByTime(now);
    }
    /**
     * 改变店铺优惠券的状态(设为过期状态)
     */
    @XxlJob("changeCoupon")
    public void changeCoupon() {
        Date now = new Date();
        log.info("设置店铺的过期优惠券为过期状态");
        // 查询需要更新的店铺id列表
        List<Long> shopIds = couponMapper.listOverdueStatusShopIds(now);
        // 取消投放
        couponService.changeCoupon(now);
        //清除缓存
        if (CollectionUtils.isNotEmpty(shopIds)) {
            for (Long shopId : shopIds) {
                cacheManagerUtil.evictCache("couponAndCouponProds", String.valueOf(shopId));
            }
        }
    }
    /**
     * 投放优惠券
     */
    @XxlJob("putOnCoupon")
    public void putOnCoupon() {
        Date now = new Date();
        log.info("投放优惠券");
        // 投放优惠券
        couponService.putonCoupon(now);
    }
}
yami-shop-cps/pom.xml
New file
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>yami-shop</artifactId>
        <groupId>com.yami.shop</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>yami-shop-cps</artifactId>
    <description>CPS模块</description>
    <packaging>pom</packaging>
    <modules>
        <module>yami-shop-cps-api</module>
        <module>yami-shop-cps-common</module>
        <module>yami-shop-cps-platform</module>
    </modules>
</project>
yami-shop-cps/yami-shop-cps-api/pom.xml
New file
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.yami.shop</groupId>
        <artifactId>yami-shop-cps</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>yami-shop-cps-api</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-security-api</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-cps-common</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
        <dependency>
            <groupId>pdd.sdk</groupId>
            <artifactId>pop-sdk</artifactId>
            <version>1.17.91</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/resources/lib/pop-sdk-1.17.91-all.jar</systemPath>
        </dependency>
    </dependencies>
</project>
yami-shop-cps/yami-shop-cps-api/src/main/java/com/yami/shop/cps/api/config/SwaggerConfiguration.java
New file
@@ -0,0 +1,35 @@
/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */
package com.yami.shop.cps.api.config;
import lombok.AllArgsConstructor;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @author yami
 */
@Configuration("cpsSwaggerConfiguration")
@AllArgsConstructor
public class SwaggerConfiguration {
    @Bean
    public GroupedOpenApi cpsRestApi() {
        return GroupedOpenApi.builder()
                .group("cps接口")
                .packagesToScan("com.yami.shop.cps.api.controller")
                .pathsToMatch("/**")
                .build();
    }
}
yami-shop-cps/yami-shop-cps-api/src/main/java/com/yami/shop/cps/api/controller/PddCpsController.java
New file
@@ -0,0 +1,102 @@
package com.yami.shop.cps.api.controller;
import com.yami.shop.bean.model.User;
import com.yami.shop.bean.param.PDDUnionExportParam;
import com.yami.shop.bean.vo.PDDUnionExportVo;
import com.yami.shop.common.config.BigSellerConfig;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.cps.commom.utils.PddUtils;
import com.yami.shop.cps.commom.vo.PddVo;
import com.yami.shop.service.CpsConfigService;
import com.yami.shop.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/p/pdd")
@Tag(name = "拼多多-cps接口")
public class PddCpsController {
    @Autowired
    private CpsConfigService cpsConfigService;
    @Autowired
    private UserService userService;
    @GetMapping("/getPddShopList")
    @Operation(summary = "根据拼多多类目查询商品列表", description = "根据拼多多类目查询商品列表")
    @Parameters({
            @Parameter(name = "catId", description = "类目Id"),
            @Parameter(name = "keyword", description = "关键词"),
            @Parameter(name = "page", description = "商品分页数 默认值1")
    })
    public ServerResponseEntity<PDDUnionExportVo> getPddShopList(@ParameterObject PDDUnionExportParam pddUnionExportParam) throws Exception {
        PddVo pddVo = cpsConfigService.getCpsConfigObject(BigSellerConfig.CPS_PDD_CONFIG, PddVo.class);
        return ServerResponseEntity.success(PddUtils.getGoodsSearch(pddUnionExportParam, pddVo));
    }
    @GetMapping("/getPddShopDetail")
    @Operation(summary = "拼多多商品详情查询", description = "拼多多商品详情查询")
    @Parameters({
            @Parameter(name = "goodsSign", description = "加密后的商品goodsId")
    })
    public ServerResponseEntity<?> getPddShopDetail(@RequestParam(value = "goodsSign") String goodsSign) throws Exception {
        PddVo pddVo = cpsConfigService.getCpsConfigObject(BigSellerConfig.CPS_PDD_CONFIG, PddVo.class);
        return ServerResponseEntity.success(PddUtils.getGoodsDetail(goodsSign, pddVo));
    }
    @GetMapping("/getPddAuthorizationUrl")
    @Operation(summary = "获取拼多多(多多进宝)授权链接" , description = "获取拼多多(多多进宝)授权链接")
    @Parameters({
            @Parameter(name = "source", description = "来源" ),
            @Parameter(name = "userId", description = "用户id" )
    })
    public ServerResponseEntity<String> getPddAuthorizationUrl(@RequestParam(value ="source") String source, @RequestParam(value ="userId") String userId) {
        User user = userService.getUserByUserId(userId);
        PddVo pddVo = cpsConfigService.getCpsConfigObject(BigSellerConfig.CPS_PDD_CONFIG, PddVo.class);
        return ServerResponseEntity.success(PddUtils.pddAuthorizationUrl(user.getUserId().toString(),source,pddVo));
    }
    @GetMapping("/getAuthorization")
    @Operation(summary = "拼多多获取APP授权链接", description = "拼多多获取APP授权链接")
    @Parameters({
            @Parameter(name = "userId", description = "用户Id")
    })
    public ServerResponseEntity<?> getAuthorization(@RequestParam(value = "userId") String userId) throws Exception {
        PddVo pddVo = cpsConfigService.getCpsConfigObject(BigSellerConfig.CPS_PDD_CONFIG, PddVo.class);
        return ServerResponseEntity.success(PddUtils.getAuthorization(userId,pddVo));
    }
    @GetMapping("/getPrivilegeLink")
    @Operation(summary = "拼多多推广链接生成" , description = "拼多多推广链接生成")
    @Parameters({
            @Parameter(name = "goodsSign", description = "商品主键id" ),
            @Parameter(name = "userId", description = "用户Id" )
    })
    public ServerResponseEntity<?> getPrivilegeLink(@RequestParam(value = "goodsSign") String goodsSign,@RequestParam(value = "userId") String userId){
        //根据用户Id 查询用户的渠道Id
        PddVo pddVo = cpsConfigService.getCpsConfigObject(BigSellerConfig.CPS_PDD_CONFIG, PddVo.class);
        String  result = null;
        try {
            Integer bind = PddUtils.getIsBind(userId,pddVo);
            if(bind == 1) {
                result = PddUtils.pddUnionRequest2(userId,goodsSign,pddVo);
            }else {
                result =PddUtils.getAuthorization(userId,pddVo);
            }
        }catch (Exception e) {
            return ServerResponseEntity.showFailMsg("推广链接生成失败");
        }
        return ServerResponseEntity.success(result);
    }
}
yami-shop-cps/yami-shop-cps-api/src/main/java/com/yami/shop/cps/api/controller/TbCpsController.java
New file
@@ -0,0 +1,174 @@
package com.yami.shop.cps.api.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.model.CpsOrder;
import com.yami.shop.bean.model.CpsShop;
import com.yami.shop.bean.model.User;
import com.yami.shop.bean.vo.JtkLinkVO;
import com.yami.shop.bean.vo.LinkVO;
import com.yami.shop.bean.vo.MtResultVo;
import com.yami.shop.bean.vo.OrderResultVo;
import com.yami.shop.common.config.BigSellerConfig;
import com.yami.shop.common.response.ResponseEnum;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.cps.commom.service.CpsMtActitvityService;
import com.yami.shop.cps.commom.service.CpsOrderService;
import com.yami.shop.cps.commom.service.CpsShopService;
import com.yami.shop.cps.commom.utils.DTKUtils;
import com.yami.shop.cps.commom.utils.MTUtils;
import com.yami.shop.cps.commom.utils.TBUtils;
import com.yami.shop.cps.commom.vo.JingDongVo;
import com.yami.shop.cps.commom.vo.MtfxlmVo;
import com.yami.shop.cps.commom.vo.TaoBaoVo;
import com.yami.shop.service.CpsConfigService;
import com.yami.shop.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
 * cps接口
 * @author zsq
 */
@RestController
@RequestMapping("/p/cps")
@Tag(name = "大淘客-cps接口")
public class TbCpsController {
    @Autowired
    private CpsConfigService cpsConfigService;
    @Autowired
    private CpsShopService cpsShopService;
    @Autowired
    private CpsOrderService cpsOrderService;
    @Autowired
    private UserService userService;
    @Autowired
    private CpsMtActitvityService cpsMtActitvityService;
    @GetMapping("/getPrivilegeLink")
    @Operation(summary = "淘宝商品高效转链查询" , description = "通过大淘客的接口查询单个商品高效转链")
    @Parameters({
            @Parameter(name = "id", description = "商品主键id" ),
            @Parameter(name = "userId", description = "用户Id" )
    })
    public ServerResponseEntity<?> getPrivilegeLink(@RequestParam(value = "id") String id,@RequestParam(value = "userId") String userId) {
        //根据用户Id 查询用户的渠道Id
        User user = userService.getUserByUserId(userId);
        if (StringUtils.isBlank(user.getSpecialId())) {
            return ServerResponseEntity.fail(ResponseEnum.EXCEPTION);
        }
        CpsShop cpsShop = cpsShopService.getById(id);
        TaoBaoVo taoBaoVo = cpsConfigService.getCpsConfigObject(BigSellerConfig.CPS_TAOBAO_CONFIG, TaoBaoVo.class);
        return ServerResponseEntity.success(DTKUtils.getTBPrivilegeLink(user.getSpecialId(),cpsShop.getGoodsId(),taoBaoVo));
    }
    @GetMapping("/getTaoBaoAuthorizationUrl")
    @Operation(summary = "获取淘宝授权链接" , description = "获取淘宝授权链接")
    @Parameters({
            @Parameter(name = "source", description = "来源" ),
            @Parameter(name = "id", description = "商品id" ),
            @Parameter(name = "userId", description = "用户id" )
    })
    public ServerResponseEntity<String> getTaoBaoAuthorizationUrl(@RequestParam(value ="source") String source, @RequestParam(value ="id") String id, @RequestParam(value ="userId") String userId) {
        User user = userService.getUserByUserId(userId);
        if (StringUtils.isBlank(user.getSpecialId())) {
            return ServerResponseEntity.success(TBUtils.taoBaoAuthorizationUrl(user.getUserId().toString(),source,id));
        }
        return ServerResponseEntity.success();
    }
    @GetMapping("/getOrderList")
    @Operation(summary = "商品订单查询" , description = "通过大淘客的接口查询订单列表")
    @Parameters({
            @Parameter(name = "userId", description = "用户id" ),
            @Parameter(name = "status", description = "动态分类")
    })
    public ServerResponseEntity<IPage<OrderResultVo>> getOrderList(PageParam<OrderResultVo> page, CpsOrder cpsOrder) {
        if (StringUtils.isBlank(cpsOrder.getUserId())) {
            return ServerResponseEntity.fail(ResponseEnum.EXCEPTION);
        }
        IPage<OrderResultVo> cpsOrderPage = cpsOrderService.cpsOrderList(cpsOrder,page);
        return ServerResponseEntity.success(cpsOrderPage);
    }
    @GetMapping("/getJdPrivilegeLink")
    @Operation(summary = "京东商品高效转链查询" , description = "通过大淘客的接口查询京东商品转链")
    @Parameters({
            @Parameter(name = "materialUrl", description = "商品Url" ),
            @Parameter(name = "userId", description = "用户Id" )
    })
    public ServerResponseEntity<?> getJdPrivilegeLink(@RequestParam(value = "materialUrl") String materialUrl,@RequestParam(value = "userId") String userId) {
        //根据用户Id 查询用户的渠道Id
        User user = userService.getUserByUserId(userId);
        JingDongVo jingDongVo = cpsConfigService.getCpsConfigObject(BigSellerConfig.CPS_JINGDONG_CONFIG, JingDongVo.class);
        return ServerResponseEntity.success(DTKUtils.getJdPrivilegeLink(materialUrl,user,jingDongVo));
    }
    @GetMapping("/getMtFinalLink")
    @Operation(summary = "美团联盟生成最终链接" , description = "美团联盟生成最终链接")
    @Parameters({
            @Parameter(name = "id", description = "活动id" ),
            @Parameter(name = "userId", description = "用户Id" ),
            @Parameter(name = "linkType", description = "链接类型(1 h5链接,2 deeplink(唤起)链接,3 中间页唤起链接,4 微信小程序唤起路径,5 团口令)" )
    })
    public ServerResponseEntity<MtResultVo> getMtFinalLink(@RequestParam(value = "id") Long id,@RequestParam(value = "userId") String userId,@RequestParam(value = "linkType") Integer linkType) {
        if(StringUtils.isBlank(userId)) {
            return ServerResponseEntity.showFailMsg("用户Id不能为空");
        }
        if(id == null) {
            return ServerResponseEntity.showFailMsg("活动Id不能为空");
        }
        return ServerResponseEntity.success(cpsMtActitvityService.getMtFinalLink(id,userId,linkType));
    }
    @GetMapping("/getJtkShopLink")
    @Operation(summary = "聚推客联盟统一活动转链" , description = "聚推客联盟统一活动转链")
    @Parameters({
            @Parameter(name = "actId", description = "活动id" ),
            @Parameter(name = "userId", description = "用户Id" )
    })
    public ServerResponseEntity<JtkLinkVO> getJtkShopLink(@RequestParam(value = "actId") String actId, @RequestParam(value = "userId") String userId) {
        return ServerResponseEntity.success(cpsMtActitvityService.getJtkShopLink(actId,userId));
    }
    @GetMapping("/getMtfxPartLink")
    @Operation(summary = "美团分销联盟取链" , description = "美团分销联盟取链")
    @Parameters({
            @Parameter(name = "activity", description = "活动id" ),
            @Parameter(name = "userId", description = "用户Id" )
    })
    public ServerResponseEntity<?> getMtfxPartLink(@RequestParam(value = "activity") String activity,@RequestParam(value = "userId") String userId) {
        User user = userService.getUserByUserId(userId);
        MtfxlmVo mtfxlmVo = cpsConfigService.getCpsConfigObject(BigSellerConfig.CPS_MTFXLM_CONFIG, MtfxlmVo.class);
        String result =MTUtils.getMtfxPartLink(activity,user,mtfxlmVo);
        JSONObject json = JSONObject.parseObject(result);
        if(StringUtils.isNotBlank(json.getString("data"))){
            LinkVO linkVO = JSONObject.parseObject(json.getString("data"),LinkVO.class);
            return ServerResponseEntity.success(linkVO);
        }else{
            return ServerResponseEntity.showFailMsg("美团分销联盟取链失败!");
        }
    }
}
yami-shop-cps/yami-shop-cps-common/pom.xml
New file
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>com.yami.shop</groupId>
        <artifactId>yami-shop-cps</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>yami-shop-cps-common</artifactId>
    <properties>
        <java.version>1.8</java.version>
        <httpclient.version>4.5.12</httpclient.version>
        <commons-lang3.version>3.8.1</commons-lang3.version>
        <jackson.version>2.11.1</jackson.version>
        <knife4j.version>2.0.3</knife4j.version>
        <skipTests>true</skipTests>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.yami.shop</groupId>
            <artifactId>yami-shop-security-common</artifactId>
            <version>${yami.shop.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>${httpclient.version}</version>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.5.22</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>${commons-lang3.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- jackson -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>taobao.sdk.source</groupId>
            <artifactId>taobao-sdk-java-source</artifactId>
            <version>1.0.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/resources/lib/taobao-sdk-java-auto_1705048877036-20240611-source.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>taobao.sdk</groupId>
            <artifactId>taobao-sddk-java</artifactId>
            <version>1.0.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/resources/lib/taobao-sdk-java-auto.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>pdd.sdk</groupId>
            <artifactId>pop-sdk</artifactId>
            <version>1.17.91</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/resources/lib/pop-sdk-1.17.91-all.jar</systemPath>
        </dependency>
    </dependencies>
</project>
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/client/AbstractDtkApiClient.java
New file
@@ -0,0 +1,121 @@
package com.yami.shop.cps.commom.client;
import com.fasterxml.jackson.core.type.TypeReference;
import com.yami.shop.cps.commom.constant.DtkApiConstant;
import com.yami.shop.cps.commom.exception.DtkApiException;
import com.yami.shop.cps.commom.exception.DtkResultEnum;
import com.yami.shop.cps.commom.http.WebUtils;
import com.yami.shop.cps.commom.response.base.DtkApiResponse;
import com.yami.shop.cps.commom.utils.Assert;
import com.yami.shop.cps.commom.utils.JsonUtil;
import com.yami.shop.cps.commom.utils.RequiredCheck;
import com.yami.shop.cps.commom.utils.SignMd5Util;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
/**
 * dtk api: AbstractDtkApiClient
 *
 * @author 1
 * @date 2020/11/10 11:37
 */
@Slf4j
public abstract class AbstractDtkApiClient implements DtkClient {
    private final String appKey;
    private final String appSecret;
    private static final String BASE_URL = "https://openapi.dataoke.com/api";
    public AbstractDtkApiClient(String appKey, String appSecret) {
        this.appKey = appKey;
        this.appSecret = appSecret;
    }
    @Override
    @SuppressWarnings("unchecked")
    public <T> T execute(DtkApiRequest<T> request) {
        String requestUrl = request.requestUrl();
        T tRsp;
        Map<String, String> requestHolderWithSign = null;
        String resultJson = null;
        try {
            // 这是一个已经设置好所有参数的key-value集
            requestHolderWithSign = getRequestHolderWithSign(request);
            Assert.notBank(requestUrl, DtkResultEnum.URL_NOT_EMPTY);
            Assert.notBank(request.apiVersion(), DtkResultEnum.VERSION_NOT_EMPTY);
            // http请求
            resultJson = WebUtils.doGet(BASE_URL + requestUrl, requestHolderWithSign);
            Assert.notBank(resultJson, DtkResultEnum.UNKNOWN_ERROR);
            TypeReference<T> responseType = request.responseType();
            tRsp = JsonUtil.jsonToPojoByTypeReference(resultJson, responseType);
        } catch (Exception ex) {
            log.error("dtk_sdk处理异常:请求地址:{},请求参数:{}", requestUrl,
                    Optional.ofNullable(requestHolderWithSign).orElse(Collections.emptyMap()).toString());
            log.error("dtk_sdk处理异常:响应结果:{}", resultJson);
            log.error("dtk_sdk处理异常:异常信息:", ex);
            if (ex instanceof DtkApiException) {
                DtkApiException exception = (DtkApiException) ex;
                return (T) DtkApiResponse.buildFail(exception.getDtkResultEnum());
            } else {
                return (T) DtkApiResponse.buildFail(DtkResultEnum.UNKNOWN_ERROR);
            }
        }
        return tRsp;
    }
    /**
     * 组装接口参数,处理加密、签名逻辑
     *
     * @param request 请求参数对象
     * @return 组装完成的完整参数
     */
    @SneakyThrows
    private Map<String, String> getRequestHolderWithSign(DtkApiRequest<?> request)
            throws IllegalAccessException {
        //校验必填参数
        Field[] fields = request.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            if (field.isAnnotationPresent(RequiredCheck.class)) {
                if (StringUtils.isEmpty(field.get(request))) {
                    throw new DtkApiException("请求参数必填项缺失!");
                }
            }
        }
        Map<String, String> textParams = request.getTextParams();
        // 创建一个Random对象
        Random random = new Random();
        // 生成一个6位的随机数,范围在0到999999之间
        int randomNumber = random.nextInt(1000000);
        String nonce = String.format("%06d", randomNumber);
        // 获取当前时间戳
        String Timer = String.format("%d", System.currentTimeMillis());
        textParams.put(DtkApiConstant.RequestCommonParam.APP_KEY, appKey);
        textParams.put(DtkApiConstant.RequestCommonParam.Nonce, nonce);
        textParams.put(DtkApiConstant.RequestCommonParam.Timer, Timer);
        // 生成签名
        String urlParams = String.format("appKey=%s&timer=%s&nonce=%s", appKey, Timer, nonce);
        String serverSign = SignMd5Util.sign(urlParams, appSecret);
        textParams.put(DtkApiConstant.RequestCommonParam.SIGN, serverSign);
        return textParams;
    }
    /**
     * 把一个字符串的第一个字母大写
     */
    private static String getMethodName(String fieldName) throws Exception {
        byte[] items = fieldName.getBytes();
        items[0] = (byte) ((char) items[0] - 'a' + 'A');
        return new String(items);
    }
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/client/ApiRequest.java
New file
@@ -0,0 +1,15 @@
package com.yami.shop.cps.commom.client;
import lombok.Data;
/**
 * 把所有参数定义在这里,直接传对象初始化client
 *
 * @author 1
 * @date 2020/11/10 11:41
 */
@Data
public class ApiRequest {
    private String appKey;
    private String appSecret;
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/client/DtkApiClient.java
New file
@@ -0,0 +1,40 @@
package com.yami.shop.cps.commom.client;
import com.yami.shop.cps.commom.exception.DtkResultEnum;
import com.yami.shop.cps.commom.utils.Assert;
/**
 * dtk api: dtkApiClient
 *
 * @author 1
 * @date 2020/11/9 16:20
 */
public class DtkApiClient extends AbstractDtkApiClient {
    private static volatile DtkApiClient dtkApiClient;
    private DtkApiClient() {
        super(null, null);
    }
    private DtkApiClient(String appKey, String appSecret) {
        super(appKey, appSecret);
    }
    public static DtkApiClient getInstance(ApiRequest apiRequest) {
        return getInstance(apiRequest.getAppKey(), apiRequest.getAppSecret());
    }
    public static DtkApiClient getInstance(String appKey, String appSecret) {
        Assert.notBank(appKey, DtkResultEnum.VERSION_NOT_EMPTY);
        Assert.notBank(appSecret, DtkResultEnum.APP_SECRET_EMPTY);
        if (dtkApiClient == null) {
            synchronized (DtkApiClient.class) {
                if (dtkApiClient == null) {
                    // 加锁
                    dtkApiClient = new DtkApiClient(appKey, appSecret);
                }
            }
        }
        return dtkApiClient;
    }
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/client/DtkApiRequest.java
New file
@@ -0,0 +1,49 @@
package com.yami.shop.cps.commom.client;
import com.fasterxml.jackson.core.type.TypeReference;
import java.util.Map;
/**
 * dtk api: some basic request interface
 *
 * @author 1
 * @date 2020/11/10 10:36
 */
public interface DtkApiRequest<T> {
    /**
     * 获取所有的Key-Value形式的文本请求参数集合。其中:
     * <ul>
     * <li>Key: 请求参数名</li>
     * <li>Value: 请求参数值</li>
     * </ul>
     *  所有实现相同ObjectUtil.objToMap(this)
     *
     * @return 文本请求参数集合
     * @throws IllegalAccessException 反射对象异常
     */
    Map<String, String> getTextParams() throws IllegalAccessException;
    /**
     * 得到当前API接口的版本
     *
     * @return API版本
     */
    String apiVersion();
    /**
     * 得到当前API的响应结果类型
     *
     * @return 响应类型
     */
    TypeReference<T> responseType();
    /**
     * 得到当前API的请求地址
     *
     * @return 请求地址
     */
    String requestUrl();
    void setVersion(String s);
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/client/DtkClient.java
New file
@@ -0,0 +1,21 @@
package com.yami.shop.cps.commom.client;
import com.yami.shop.cps.commom.exception.DtkApiException;
/**
 * dtk api: DtkClient,Provide an execution interface
 *
 * @author 1
 * @date 2020/11/10 11:24
 */
public interface DtkClient {
    /**
     * 根据请求参数执行逻辑
     *
     * @param request 请求参数
     * @param <T>     请求泛型
     * @return 返回结果与request对应
     * @throws DtkApiException dtk自定义异常
     */
    <T> T execute(DtkApiRequest<T> request);
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/constant/DtkApiConstant.java
New file
@@ -0,0 +1,48 @@
package com.yami.shop.cps.commom.constant;
/**
 * dtk api: constant class
 *
 * @author 1
 * @date 2020/11/9 16:27
 */
public class DtkApiConstant {
    private DtkApiConstant() {
    }
    public static final String EMPTY_STR = "";
    public static final String ENCRYPT_TYPE_MD5 = "MD5";
    public static final String CLASS_TYPE = "class";
    /**
     * 默认时间格式
     **/
    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /**
     * Date默认时区
     **/
    public static final String DATE_TIMEZONE = "GMT+8";
    public static final String SDK_VERSION = "dtk-java-open-platform-sdk-1.0.0";
    public static class Charset {
        public static final String UTF_8 = "UTF-8";
    }
    public static class RequestCommonParam {
        public static final String SIGN = "signRan";
        public static final String Nonce = "nonce";
        public static final String Timer = "timer";
        public static final String APP_KEY = "appKey";
        public static final String APP_SECRET = "appSecret";
        public static final String REQUEST_URL = "requestUrl";
    }
    public static class Domain {
        public static final String PROD = "https://openapi.dataoke.com";
    }
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/controller/base/BaseController.java
New file
@@ -0,0 +1,56 @@
package com.yami.shop.cps.commom.controller.base;
import com.yami.shop.cps.commom.client.DtkApiClient;
import com.yami.shop.cps.commom.client.DtkClient;
import com.yami.shop.cps.commom.constant.DtkApiConstant;
import com.yami.shop.cps.commom.exception.DtkResultEnum;
import com.yami.shop.cps.commom.request.putstorage.DtkGoodsListRequest;
import com.yami.shop.cps.commom.response.base.DtkApiResponse;
import com.yami.shop.cps.commom.response.base.DtkPageResponse;
import com.yami.shop.cps.commom.response.putstorage.DtkGoodsListItemResponse;
import com.yami.shop.cps.commom.utils.Assert;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/**
 * dtk api: base controller
 *
 * @author baige
 * @date 2020/11/13 14:21
 */
@Component
public class BaseController {
    @Resource
    private HttpServletRequest request;
    private DtkApiClient instance;
    protected DtkClient getDtkClient() {
        String appKey = getClientHeader(DtkApiConstant.RequestCommonParam.APP_KEY);
        Assert.notBank(appKey, DtkResultEnum.APP_KEY_EMPTY);
        String appSecret = getClientHeader(DtkApiConstant.RequestCommonParam.APP_SECRET);
        Assert.notBank(appSecret, DtkResultEnum.APP_SECRET_EMPTY);
        if (instance == null) {
            synchronized (BaseController.class) {
                if (instance == null) {
                    this.instance = DtkApiClient.getInstance(appKey, appSecret);
                }
            }
        }
        return this.instance;
    }
    /**
     * 从header获取appKey和appSecret
     */
    private String getClientHeader(String headerKey) {
        return request.getHeader(headerKey);
    }
    protected String getRequestUrl() {
        String requestUrl = request.getRequestURI();
        return String.format("%s%s", DtkApiConstant.Domain.PROD, requestUrl);
    }
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/controller/base/TaoBaoUnionController.java
New file
@@ -0,0 +1,130 @@
package com.yami.shop.cps.commom.controller.base;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yami.shop.bean.model.User;
import com.yami.shop.common.config.BigSellerConfig;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.cps.commom.service.CpsMtActitvityService;
import com.yami.shop.cps.commom.utils.PddUtils;
import com.yami.shop.cps.commom.utils.TBUtils;
import com.yami.shop.cps.commom.vo.PddVo;
import com.yami.shop.service.CpsConfigService;
import com.yami.shop.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.TreeMap;
@Slf4j
@Controller
@RequestMapping("/tb/front/tbUnion")
@Api(tags = "cps回调接口")
public class TaoBaoUnionController {
    @Autowired
    private UserService userService;
    @Autowired
    private CpsConfigService cpsConfigService;
    @Autowired
    private CpsMtActitvityService cpsMtActitvityService;
    private String jumpH5Url ="http://127.0.0.1:8848/luckH5/index.html";
    @Operation(summary = "淘宝回调" , description = "淘宝回调")
    @RequestMapping(value = "/taobaoCallback", method = RequestMethod.GET)
    public String taobaoCallback(HttpServletRequest request){
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        String[] split = state.split("-");
        String userId= split[0];
        String source= split[1];
        if(userId!=null) {
            try {
                //获取用户授权的accessToken
                String token = TBUtils.getToken(code);
                JSONObject json = JSONObject.parseObject(token);
                JSONObject authToken = JSONObject.parseObject(json.getString("top_auth_token_create_response"));
                JSONObject tokenResult = JSON.parseObject(authToken.getString("token_result"));
                String accessToken = tokenResult.getString("access_token");
                //System.out.println("accessToken--------------------"+accessToken);
                //私域用户渠道备案
                String relationInfo = TBUtils.publisherInfoRelationSave(accessToken);
                json = JSONObject.parseObject(relationInfo);
                if (json.containsKey("tbk_sc_publisher_info_save_response")) {
                    JSONObject publisherInfo = JSONObject.parseObject(json.getString("tbk_sc_publisher_info_save_response"));
                    JSONObject relationData = JSON.parseObject(publisherInfo.getString("data"));
                    //渠道id
                    String relationId = relationData.getString("relation_id");
                    //私域用户会员备案
                    String memberInfo = TBUtils.publisherInfoMemberSave(accessToken);
                    json = JSONObject.parseObject(memberInfo);
                    JSONObject fansInfo = JSONObject.parseObject(json.getString("tbk_sc_publisher_info_save_response"));
                    JSONObject fansData = JSON.parseObject(fansInfo.getString("data"));
                    //会员id
                    String specialId = fansData.getString("special_id");
                    //System.out.println("specialId--------------------"+specialId);
                    User user = userService.getRelationAndSpecialId(relationId,specialId);
                    if(!ObjectUtils.isEmpty(user)){
                        return "redirect:"+jumpH5Url+"?source="+source+"&type=error&userId="+userId;
                    }
                    user = userService.getById(userId);
                    if (!ObjectUtils.isEmpty(user)) {
                        user.setRelationId(relationId);
                        user.setSpecialId(specialId);
                        userService.updateById(user);
                    }
                } else {
                    throw new YamiShopBindException("不支持同人邀请!");
                }
            } catch (Exception e) {
                System.out.println("淘宝客回调异常:");
            }
        }
        return "redirect:"+jumpH5Url+"?source="+source+"&&type=success&userId="+userId;
    }
    @Operation(summary = "美团联盟回调" , description = "美团联盟回调")
    @PostMapping("/mtOrderCallback")
    public Map<String, String> mtOrderCallback(@RequestBody TreeMap<String, String> params){
        return cpsMtActitvityService.mtOrderCallback(params);
    }
    @Operation(summary = "拼多多回调" , description = "美团联盟回调")
    @RequestMapping(value = "/pddCallback", method = RequestMethod.GET)
    public String pddCallback(HttpServletRequest request){
        // 获取code参数
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        String[] split = state.split("-");
        Integer userId = Integer.valueOf(split[0]);
        String source = split[1];
        if (userId != null) {
            try {
                //获取用户授权的accessToken
                PddVo pddVo = cpsConfigService.getCpsConfigObject(BigSellerConfig.CPS_PDD_CONFIG, PddVo.class);
                String token = PddUtils.getToken(code,pddVo);
                JSONObject json = JSONObject.parseObject(token);
                JSONObject authToken = JSONObject.parseObject(json.getString("pop_auth_token_create_response"));
                String accessToken = authToken.getString("access_token");
                String ownerId = authToken.getString("owner_id");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "redirect:" + jumpH5Url + "?source=" + source + "&type=success";
    }
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/exception/DtkApiException.java
New file
@@ -0,0 +1,28 @@
package com.yami.shop.cps.commom.exception;
import lombok.Getter;
/**
 * dtk api: custom business exception
 *
 * @author 1
 * @date 2020/11/10 11:55
 */
@Getter
public class DtkApiException extends RuntimeException {
    private DtkResultEnum dtkResultEnum;
    public DtkApiException(String message) {
        super(message);
    }
    public DtkApiException(DtkResultEnum dtkResultEnum) {
        super(dtkResultEnum.getMsg());
        this.dtkResultEnum = dtkResultEnum;
    }
    @Override
    public Throwable fillInStackTrace() {
        return this;
    }
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/exception/DtkResultEnum.java
New file
@@ -0,0 +1,38 @@
package com.yami.shop.cps.commom.exception;
/**
 * dtk api: result enum
 *
 * @author 1
 * @date 2020/11/10 17:49
 */
public enum DtkResultEnum implements Result {
    UNKNOWN_ERROR(-1, "服务器错误"),
    SUCCESS(0, "成功"),
    URL_NOT_EMPTY(1, "请求地址不能为空"),
    RANK_TYPE_ERROR(10004, "榜单类型为空或不正确"),
    APP_KEY_EMPTY(10016, "appKey不能为空"),
    VERSION_NOT_EMPTY(10017, "版本号不能为空"),
    APP_SECRET_EMPTY(10018, "appSecret不能为空"),
    ;
    private final int code;
    private final String msg;
    DtkResultEnum(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    @Override
    public int getCode() {
        return this.code;
    }
    @Override
    public String getMsg() {
        return this.msg;
    }
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/exception/Result.java
New file
@@ -0,0 +1,23 @@
package com.yami.shop.cps.commom.exception;
/**
 * dtk api: result abstract interface
 *
 * @author 1
 * @date 2020/11/10 17:49
 */
public interface Result {
    /**
     * 获取结果code
     *
     * @return code
     */
    int getCode();
    /**
     * 获取结果信息
     *
     * @return message
     */
    String getMsg();
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/http/Logger.java
New file
@@ -0,0 +1,217 @@
package com.yami.shop.cps.commom.http;
import com.yami.shop.cps.commom.constant.DtkApiConstant;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
/**
 * 日志打印
 *
 * @author xx
 * @date 2020/12/2 18:08
 */
@Slf4j
public class Logger {
    private static final String OS_NAME = System.getProperties().getProperty("os.name");
    private static boolean needEnableLogger = true;
    private static String ip = null;
    public static void setNeedEnableLogger(boolean needEnableLogger) {
        Logger.needEnableLogger = needEnableLogger;
    }
    private Logger() {
    }
    public static void logCommError(Exception e, String url, String appKey, String method,
                                    Map<String, String> params) {
        if (!needEnableLogger) {
            return;
        }
        _logCommError(e, null, url, appKey, method, params);
    }
    public static void logCommError(Exception e, HttpURLConnection conn, String appKey,
                                    String method, Map<String, String> params) {
        if (!needEnableLogger) {
            return;
        }
        _logCommError(e, conn, null, appKey, method, params);
    }
    public static void logCommError(Exception e, String url, String appKey, String method,
                                    byte[] content) {
        if (!needEnableLogger) {
            return;
        }
        String contentString = new String(content, StandardCharsets.UTF_8);
        logCommError(e, url, appKey, method, contentString);
    }
    private static void logCommError(Exception e, String url, String appKey, String method,
                                     String content) {
        Map<String, String> params = parseParam(content);
        _logCommError(e, null, url, appKey, method, params);
    }
    /**
     * 通讯错误日志
     */
    private static void _logCommError(Exception e, HttpURLConnection conn, String url,
                                      String appKey, String method, Map<String, String> params) {
        DateFormat df = new SimpleDateFormat(DtkApiConstant.DATE_TIME_FORMAT);
        df.setTimeZone(TimeZone.getTimeZone(DtkApiConstant.DATE_TIMEZONE));
        String sdkName = DtkApiConstant.SDK_VERSION;
        String urlStr = null;
        String rspCode = "";
        if (conn != null) {
            try {
                urlStr = conn.getURL().toString();
                rspCode = "HTTP_ERROR_" + conn.getResponseCode();
            } catch (IOException ioe) {
                log.error(ioe.getMessage());
            }
        } else {
            urlStr = url;
            rspCode = "";
        }
        StringBuilder sb = new StringBuilder();
        // 时间
        sb.append(df.format(new Date()));
        sb.append("^_^");
        // API
        sb.append(method);
        sb.append("^_^");
        // APP
        sb.append(appKey);
        sb.append("^_^");
        // IP地址
        sb.append(getIp());
        sb.append("^_^");
        // 操作系统
        sb.append(OS_NAME);
        // SDK名字,这是例子,请换成其他名字
        sb.append("^_^");
        sb.append(sdkName);
        sb.append("^_^");
        // 请求URL
        sb.append(urlStr);
        sb.append("^_^");
        sb.append(rspCode);
        sb.append("^_^");
        sb.append((e.getMessage() + "").replaceAll("\r\n", " "));
        log.error(sb.toString());
    }
    public static void logCommError(Exception e, HttpURLConnection conn, String appKey,
                                    String method, byte[] content) {
        if (!needEnableLogger) {
            return;
        }
        String contentString;
        try {
            contentString = new String(content, StandardCharsets.UTF_8);
            logCommError(e, conn, appKey, method, contentString);
        } catch (Exception e1) {
            log.error(e1.getMessage());
        }
    }
    private static Map<String, String> parseParam(String contentString) {
        Map<String, String> params = new HashMap<>(16);
        if (contentString == null || "".equals(contentString.trim())) {
            return params;
        }
        String[] paramsArray = contentString.split("&");
        for (String param : paramsArray) {
            String[] keyValue = param.split("=");
            if (keyValue.length == 2) {
                params.put(keyValue[0], keyValue[1]);
            }
        }
        return params;
    }
    /**
     * 通讯错误日志
     */
    private static void logCommError(Exception e, HttpURLConnection conn, String appKey,
                                     String method, String content) {
        Map<String, String> params = parseParam(content);
        logCommError(e, conn, null, appKey, method, params);
    }
    /**
     * 通讯错误日志
     */
    private static void logCommError(Exception e, HttpURLConnection conn, String url,
                                     String appKey, String method, Map<String, String> params) {
        DateFormat df = new SimpleDateFormat(DtkApiConstant.DATE_TIME_FORMAT);
        df.setTimeZone(TimeZone.getTimeZone(DtkApiConstant.DATE_TIMEZONE));
        String sdkName = DtkApiConstant.SDK_VERSION;
        String urlStr = null;
        String rspCode = "";
        if (conn != null) {
            try {
                urlStr = conn.getURL().toString();
                rspCode = "HTTP_ERROR_" + conn.getResponseCode();
            } catch (IOException ioe) {
                log.error(ioe.getMessage());
            }
        } else {
            urlStr = url;
            rspCode = "";
        }
        StringBuilder sb = new StringBuilder();
        // 时间
        sb.append(df.format(new Date()));
        sb.append("^_^");
        // API
        sb.append(method);
        sb.append("^_^");
        // APP
        sb.append(appKey);
        sb.append("^_^");
        // IP地址
        sb.append(getIp());
        sb.append("^_^");
        // 操作系统
        sb.append(OS_NAME);
        sb.append("^_^");
        // SDK名字,这是例子,请换成其他名字
        sb.append(sdkName);
        sb.append("^_^");
        // 请求URL
        sb.append(urlStr);
        sb.append("^_^");
        sb.append(rspCode);
        sb.append("^_^");
        sb.append((e.getMessage() + "").replaceAll("\r\n", " "));
        log.error(sb.toString());
    }
    public static String getIp() {
        if (ip == null) {
            try {
                ip = InetAddress.getLocalHost().getHostAddress();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return ip;
    }
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/http/StringUtils.java
New file
@@ -0,0 +1,169 @@
package com.yami.shop.cps.commom.http;
import java.util.Arrays;
/**
 * 字符传工具类
 *
 * @author baige
 * @date 2020/12/2 17:21
 */
public class StringUtils {
    private StringUtils() {
    }
    /**
     * 检查指定的字符串是否为空。
     * <ul>
     * <li>SysUtils.isEmpty(null) = true</li>
     * <li>SysUtils.isEmpty("") = true</li>
     * <li>SysUtils.isEmpty("   ") = true</li>
     * <li>SysUtils.isEmpty("abc") = false</li>
     * </ul>
     *
     * @param value 待检查的字符串
     * @return true/false
     */
    public static boolean isEmpty(String value) {
        int strLen;
        if (value == null || (strLen = value.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if ((!Character.isWhitespace(value.charAt(i)))) {
                return false;
            }
        }
        return true;
    }
    /**
     * 检查对象是否为数字型字符串,包含负数开头的。
     */
    public static boolean isNumeric(Object obj) {
        if (obj == null) {
            return false;
        }
        char[] chars = obj.toString().toCharArray();
        int length = chars.length;
        if (length < 1) {
            return false;
        }
        int i = 0;
        if (length > 1 && chars[0] == '-') {
            i = 1;
        }
        for (; i < length; i++) {
            if (!Character.isDigit(chars[i])) {
                return false;
            }
        }
        return true;
    }
    /**
     * 检查指定的字符串列表是否不为空。
     */
    public static boolean areNotEmpty(String... values) {
        boolean result = true;
        if (values == null || values.length == 0) {
            result = false;
        } else {
            for (String value : values) {
                result &= !isEmpty(value);
            }
        }
        return result;
    }
    /**
     * 把通用字符编码的字符串转化为汉字编码。
     */
    public static String unicodeToChinese(String unicode) {
        StringBuilder out = new StringBuilder();
        if (!isEmpty(unicode)) {
            for (int i = 0; i < unicode.length(); i++) {
                out.append(unicode.charAt(i));
            }
        }
        return out.toString();
    }
    /**
     * 过滤不可见字符
     */
    public static String stripNonValidXmlCharacters(String input) {
        if (input == null || ("".equals(input))) {
            return "";
        }
        StringBuilder out = new StringBuilder();
        char current;
        for (int i = 0; i < input.length(); i++) {
            current = input.charAt(i);
            boolean flag = current == 0x9 || current == 0xA || current == 0xD || current >= 0x20 && current <= 0xD7FF || current >= 0xE000 && current <= 0xFFFD;
            if (flag) {
                out.append(current);
            }
        }
        return out.toString();
    }
    public static String leftPad(String str, int size, char padChar) {
        if (str == null) {
            return null;
        } else {
            int pads = size - str.length();
            if (pads <= 0) {
                return str;
            } else {
                return pads > 8192 ? leftPad(str, size, String.valueOf(padChar)) : padding(pads, padChar).concat(str);
            }
        }
    }
    public static String leftPad(String str, int size, String padStr) {
        if (str == null) {
            return null;
        } else {
            if (isEmpty(padStr)) {
                padStr = " ";
            }
            int padLen = padStr.length();
            int strLen = str.length();
            int pads = size - strLen;
            if (pads <= 0) {
                return str;
            } else if (padLen == 1 && pads <= 8192) {
                return leftPad(str, size, padStr.charAt(0));
            } else if (pads == padLen) {
                return padStr.concat(str);
            } else if (pads < padLen) {
                return padStr.substring(0, pads).concat(str);
            } else {
                char[] padding = new char[pads];
                char[] padChars = padStr.toCharArray();
                for (int i = 0; i < pads; ++i) {
                    padding[i] = padChars[i % padLen];
                }
                return (new String(padding)).concat(str);
            }
        }
    }
    private static String padding(int repeat, char padChar) throws IndexOutOfBoundsException {
        if (repeat < 0) {
            throw new IndexOutOfBoundsException("Cannot pad a negative amount: " + repeat);
        } else {
            char[] buf = new char[repeat];
            Arrays.fill(buf, padChar);
            return new String(buf);
        }
    }
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/http/WebUtils.java
New file
@@ -0,0 +1,484 @@
package com.yami.shop.cps.commom.http;
import com.yami.shop.cps.commom.constant.DtkApiConstant;
import lombok.extern.slf4j.Slf4j;
import javax.net.ssl.*;
import java.io.*;
import java.lang.reflect.Field;
import java.net.*;
import java.net.Proxy.Type;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
 * 网络工具类。
 *
 * @author xx
 * @since xx
 */
@Slf4j
public class WebUtils {
    private static final String DEFAULT_CHARSET = DtkApiConstant.Charset.UTF_8;
    private static final String METHOD_POST = "POST";
    private static final String METHOD_GET = "GET";
    private static SSLContext ctx = null;
    private static HostnameVerifier verifier = null;
    private static SSLSocketFactory socketFactory = null;
    private static int keepAliveTimeout = 0;
    /**
     * 是否校验SSL服务端证书,默认为需要校验
     */
    private static volatile boolean needCheckServerTrusted = true;
    /**
     * 设置是否校验SSL服务端证书
     *
     * @param needCheckServerTrusted true:需要校验(默认,推荐);
     *                               <p>
     *                               false:不需要校验(仅当部署环境不便于进行服务端证书校验,且已有其他方式确保通信安全时,可以关闭SSL服务端证书校验功能)
     */
    public static void setNeedCheckServerTrusted(boolean needCheckServerTrusted) {
        WebUtils.needCheckServerTrusted = needCheckServerTrusted;
    }
    /**
     * 设置KeepAlive连接超时时间,一次HTTP请求完成后,底层TCP连接将尝试尽量保持该超时时间后才关闭,以便其他HTTP请求复用TCP连接
     * <p>
     * KeepAlive连接超时时间设置为0,表示使用默认的KeepAlive连接缓存时长(目前为5s)
     * <p>
     * 连接并非一定能保持指定的KeepAlive超时时长,比如服务端断开了连接
     * <p>
     * 注:该方法目前只在JDK8上测试有效
     *
     * @param timeout KeepAlive超时时间,单位秒
     */
    public static void setKeepAliveTimeout(int timeout) {
        if (timeout < 0 || timeout > 60) {
            throw new RuntimeException("keep-alive timeout value must be between 0 and 60.");
        }
        keepAliveTimeout = timeout;
    }
    private static class DefaultTrustManager implements X509TrustManager {
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
        @Override
        public void checkClientTrusted(X509Certificate[] chain,
                                       String authType) throws CertificateException {
        }
        @Override
        public void checkServerTrusted(X509Certificate[] chain,
                                       String authType) throws CertificateException {
        }
    }
    static {
        try {
            ctx = SSLContext.getInstance("TLS");
            ctx.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager()},
                    new SecureRandom());
            ctx.getClientSessionContext().setSessionTimeout(15);
            ctx.getClientSessionContext().setSessionCacheSize(1000);
            socketFactory = ctx.getSocketFactory();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        verifier = (hostname, session) -> {
            return false; //不允许URL的主机名和服务器的标识主机名不匹配的情况
        };
    }
    private WebUtils() {
    }
    /**
     * 执行HTTP GET请求。
     *
     * @param url    请求地址
     * @param params 请求参数
     * @return 响应字符串
     * @throws IOException
     */
    public static String doGet(String url, Map<String, String> params) throws IOException {
        return doGet(url, params, DEFAULT_CHARSET);
    }
    /**
     * 执行HTTP GET请求。
     *
     * @param url     请求地址
     * @param params  请求参数
     * @param charset 字符集,如UTF-8, GBK, GB2312
     * @return 响应字符串
     * @throws IOException
     */
    public static String doGet(String url, Map<String, String> params,
                               String charset) throws IOException {
        HttpURLConnection conn = null;
        String rsp;
        try {
            String ctype = "application/x-www-form-urlencoded;charset=" + charset;
            String query = buildQuery(params, charset);
            try {
                conn = getConnection(buildGetUrl(url, query), METHOD_GET, ctype);
            } catch (IOException e) {
                Logger.logCommError(e, url, params.get("appKey"), null, params);
                throw e;
            }
            try {
                rsp = getResponseAsString(conn);
            } catch (IOException e) {
                Logger.logCommError(e, conn, params.get("appKey"), null, params);
                throw e;
            }
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
        return rsp;
    }
    public static HttpURLConnection getConnection(URL url, String method, String ctype) throws IOException {
        return getConnection(url, method, ctype, null);
    }
    public static HttpURLConnection getConnection(URL url, String method, String ctype,
                                                  String proxyHost, int proxyPort) throws IOException {
        Proxy proxy = new Proxy(Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
        return getConnection(url, method, ctype, proxy);
    }
    private static HttpURLConnection getConnection(URL url, String method, String ctype, Proxy proxy) throws IOException {
        HttpURLConnection conn = null;
        if ("https".equals(url.getProtocol())) {
            HttpsURLConnection connHttps = null;
            if (proxy != null) {
                connHttps = (HttpsURLConnection) url.openConnection(proxy);
            } else {
                connHttps = (HttpsURLConnection) url.openConnection();
            }
            if (!needCheckServerTrusted) {
                //设置不校验服务端证书的SSLContext
                connHttps.setSSLSocketFactory(socketFactory);
                connHttps.setHostnameVerifier(verifier);
            }
            conn = connHttps;
        } else {
            if (proxy != null) {
                conn = (HttpURLConnection) url.openConnection(proxy);
            } else {
                conn = (HttpURLConnection) url.openConnection();
            }
        }
        conn.setRequestMethod(method);
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setRequestProperty("Accept", "text/plain,text/xml,text/javascript,text/html,application/json");
        conn.setRequestProperty("User-Agent", "aop-sdk-java");
        conn.setRequestProperty("Content-Type", ctype);
        conn.setRequestProperty("Client-Sdk-Type","java");
        return conn;
    }
    private static URL buildGetUrl(String strUrl, String query) throws IOException {
        URL url = new URL(strUrl);
        if (StringUtils.isEmpty(query)) {
            return url;
        }
        if (StringUtils.isEmpty(url.getQuery())) {
            if (strUrl.endsWith("?")) {
                strUrl = strUrl + query;
            } else {
                strUrl = strUrl + "?" + query;
            }
        } else {
            if (strUrl.endsWith("&")) {
                strUrl = strUrl + query;
            } else {
                strUrl = strUrl + "&" + query;
            }
        }
        return new URL(strUrl);
    }
    public static String buildQuery(Map<String, String> params, String charset) throws IOException {
        if (params == null || params.isEmpty()) {
            return null;
        }
        StringBuilder query = new StringBuilder();
        Set<Entry<String, String>> entries = params.entrySet();
        boolean hasParam = false;
        for (Entry<String, String> entry : entries) {
            String name = entry.getKey();
            String value = entry.getValue();
            // 忽略参数名或参数值为空的参数
            if (StringUtils.areNotEmpty(name, value)) {
                if (hasParam) {
                    query.append("&");
                } else {
                    hasParam = true;
                }
                query.append(name).append("=").append(URLEncoder.encode(value, charset));
            }
        }
        return query.toString();
    }
    protected static String getResponseAsString(HttpURLConnection conn) throws IOException {
        String charset = getResponseCharset(conn.getContentType());
        //此时设置KeepAlive超时所需数据结构才刚初始化完整,可以通过反射修改
        //同时也不宜将修改时机再滞后,因为可能后续连接缓存类已经消费了默认的KeepAliveTimeout值,再修改已经无效
        setKeepAliveTimeout(conn);
        InputStream es = conn.getErrorStream();
        if (es == null) {
            return getStreamAsString(conn.getInputStream(), charset);
        } else {
            String msg = getStreamAsString(es, charset);
            if (StringUtils.isEmpty(msg)) {
                throw new IOException(conn.getResponseCode() + ":" + conn.getResponseMessage());
            } else {
                throw new IOException(msg);
            }
        }
    }
    private static String getStreamAsString(InputStream stream, String charset) throws IOException {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream, charset));
            StringWriter writer = new StringWriter();
            char[] chars = new char[256];
            int count = 0;
            while ((count = reader.read(chars)) > 0) {
                writer.write(chars, 0, count);
            }
            return writer.toString();
        } finally {
            if (stream != null) {
                stream.close();
            }
        }
    }
    private static String getResponseCharset(String ctype) {
        String charset = DEFAULT_CHARSET;
        if (!StringUtils.isEmpty(ctype)) {
            String[] params = ctype.split(";");
            for (String param : params) {
                param = param.trim();
                if (param.startsWith("charset")) {
                    String[] pair = param.split("=", 2);
                    if (pair.length == 2) {
                        if (!StringUtils.isEmpty(pair[1])) {
                            charset = pair[1].trim();
                        }
                    }
                    break;
                }
            }
        }
        return charset;
    }
    /**
     * 使用默认的UTF-8字符集反编码请求参数值。
     *
     * @param value 参数值
     * @return 反编码后的参数值
     */
    public static String decode(String value) {
        return decode(value, DEFAULT_CHARSET);
    }
    /**
     * 使用默认的UTF-8字符集编码请求参数值。
     *
     * @param value 参数值
     * @return 编码后的参数值
     */
    public static String encode(String value) {
        return encode(value, DEFAULT_CHARSET);
    }
    /**
     * 使用指定的字符集反编码请求参数值。
     *
     * @param value   参数值
     * @param charset 字符集
     * @return 反编码后的参数值
     */
    public static String decode(String value, String charset) {
        String result = null;
        if (!StringUtils.isEmpty(value)) {
            try {
                result = URLDecoder.decode(value, charset);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return result;
    }
    /**
     * 使用指定的字符集编码请求参数值。
     *
     * @param value   参数值
     * @param charset 字符集
     * @return 编码后的参数值
     */
    public static String encode(String value, String charset) {
        String result = null;
        if (!StringUtils.isEmpty(value)) {
            try {
                result = URLEncoder.encode(value, charset);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return result;
    }
    private static Map<String, String> getParamsFromUrl(String url) {
        Map<String, String> map = null;
        if (url != null && url.indexOf('?') != -1) {
            map = splitUrlQuery(url.substring(url.indexOf('?') + 1));
        }
        if (map == null) {
            map = new HashMap<>();
        }
        return map;
    }
    /**
     * 从URL中提取所有的参数。
     *
     * @param query URL地址
     * @return 参数映射
     */
    public static Map<String, String> splitUrlQuery(String query) {
        Map<String, String> result = new HashMap<String, String>();
        String[] pairs = query.split("&");
        if (pairs != null && pairs.length > 0) {
            for (String pair : pairs) {
                String[] param = pair.split("=", 2);
                if (param != null && param.length == 2) {
                    result.put(param[0], param[1]);
                }
            }
        }
        return result;
    }
    public static String buildForm(String baseUrl, Map<String, String> parameters) {
        StringBuilder sb = new StringBuilder();
        sb.append("<form name=\"punchout_form\" method=\"post\" action=\"");
        sb.append(baseUrl);
        sb.append("\">\n");
        sb.append(buildHiddenFields(parameters));
        sb.append("<input type=\"submit\" value=\"立即支付\" style=\"display:none\" >\n");
        sb.append("</form>\n");
        sb.append("<script>document.forms[0].submit();</script>");
        String form = sb.toString();
        return form;
    }
    private static String buildHiddenFields(Map<String, String> parameters) {
        if (parameters == null || parameters.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        Set<String> keys = parameters.keySet();
        for (String key : keys) {
            String value = parameters.get(key);
            // 除去参数中的空值
            if (key == null || value == null) {
                continue;
            }
            sb.append(buildHiddenField(key, value));
        }
        return sb.toString();
    }
    private static String buildHiddenField(String key, String value) {
        StringBuilder sb = new StringBuilder();
        sb.append("<input type=\"hidden\" name=\"");
        sb.append(key);
        sb.append("\" value=\"");
        //转义双引号
        String a = value.replace("\"", "&quot;");
        sb.append(a).append("\">\n");
        return sb.toString();
    }
    /**
     * 由于HttpUrlConnection不支持设置KeepAlive超时时间,该方法通过反射机制设置
     *
     * @param connection 需要设置KeepAlive的连接
     */
    private static void setKeepAliveTimeout(HttpURLConnection connection) {
        if (keepAliveTimeout == 0) {
            return;
        }
        try {
            Field delegateHttpsUrlConnectionField = Class.forName("sun.net.www.protocol.https.HttpsURLConnectionImpl").getDeclaredField(
                    "delegate");
            delegateHttpsUrlConnectionField.setAccessible(true);
            Object delegateHttpsUrlConnection = delegateHttpsUrlConnectionField.get(connection);
            Field httpClientField = Class.forName("sun.net.www.protocol.http.HttpURLConnection").getDeclaredField("http");
            httpClientField.setAccessible(true);
            Object httpClient = httpClientField.get(delegateHttpsUrlConnection);
            Field keepAliveTimeoutField = Class.forName("sun.net.www.http.HttpClient").getDeclaredField("keepAliveTimeout");
            keepAliveTimeoutField.setAccessible(true);
            keepAliveTimeoutField.setInt(httpClient, keepAliveTimeout);
        } catch (Throwable ignored) {
            //设置KeepAlive超时只是一种优化辅助手段,设置失败不应阻塞主链路,设置失败不应影响功能
        }
    }
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/base/DtkPageParamRequest.java
New file
@@ -0,0 +1,23 @@
package com.yami.shop.cps.commom.request.base;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
 * dtk api: page param,independent of business entity
 *
 * @author 1
 * @date 2020/11/9 17:15
 */
@Getter
@Setter
public class DtkPageParamRequest {
    @ApiModelProperty(value = "每页条数,默认为100,最大值200,若小于10,则按10条处理,每页条数仅支持输入10,50,100,200", required = true, example =
            "10")
    private Integer pageSize;
    @ApiModelProperty(value = "分页id,默认为1,支持传统的页码分页方式和scroll_id分页方式,根据用户自身需求传入值。示例1:商品入库,则首次传入1,后续传入接口返回的pageid" +
            ",接口将持续返回符合条件的完整商品列表,该方式可以避免入口商品重复;示例2:根据pageSize和totalNum计算出总页数,按照需求返回指定页的商品(该方式可能在临近页取到重复商品)", required
            = true, example = "1")
    private String pageId;
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/base/DtkUrlParamRequest.java
New file
@@ -0,0 +1,19 @@
package com.yami.shop.cps.commom.request.base;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
 * dtk api: url param,independent of business entity
 *
 * @author 1
 * @date 2020/11/9 17:15
 */
@Getter
@Setter
public class DtkUrlParamRequest {
    @ApiModelProperty(value = "请求地址", hidden = true)
    private String requestUrl;
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkActivityLinkRequest.java
New file
@@ -0,0 +1,59 @@
package com.yami.shop.cps.commom.request.mastertool;
import com.fasterxml.jackson.core.type.TypeReference;
import com.yami.shop.cps.commom.client.DtkApiRequest;
import com.yami.shop.cps.commom.response.base.DtkApiResponse;
import com.yami.shop.cps.commom.response.mastertool.DtkActivityLinkResponse;
import com.yami.shop.cps.commom.utils.ObjectUtil;
import com.yami.shop.cps.commom.utils.RequiredCheck;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.Map;
/**
 * 官方活动会场转链请求参数实体
 *
 * @author 1
 * @date 2020/11/10 18:04
 */
@Getter
@Setter
public class DtkActivityLinkRequest implements DtkApiRequest<DtkApiResponse<DtkActivityLinkResponse>> {
    @ApiModelProperty(value = "版本号", example = "v1.0.0")
    private String version = "1.0.0";
    @RequiredCheck
    @ApiModelProperty(value = "联盟官方活动ID,从联盟官方活动页获取或从大淘客官方活动推广接口获取", required = true)
    private String promotionSceneId;
    @ApiModelProperty(value = "推广pid,默认为在”我的应用“添加的pid")
    private String pid;
    @ApiModelProperty(value = "渠道id将会和传入的pid进行验证,验证通过将正常转链,请确认填入的渠道id是正确的")
    private String relationId;
    @ApiModelProperty(value = "自定义输入串,英文和数字组成,长度不能大于12个字符,区分不同的推广渠道")
    private String unionId;
    @ApiModelProperty("官方活动会场转链请求path")
    private final String requestPath = "/tb-service/activity-link";
    @Override
    public Map<String, String> getTextParams() throws IllegalAccessException {
        return ObjectUtil.objToMap(this);
    }
    @Override
    public String apiVersion() {
        return this.version;
    }
    @Override
    public TypeReference<DtkApiResponse<DtkActivityLinkResponse>> responseType() {
        return new TypeReference<DtkApiResponse<DtkActivityLinkResponse>>() {
        };
    }
    @Override
    public String requestUrl() {
        return this.requestPath;
    }
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkCommodityMaterialsRequest.java
New file
@@ -0,0 +1,53 @@
package com.yami.shop.cps.commom.request.mastertool;
import com.fasterxml.jackson.core.type.TypeReference;
import com.yami.shop.cps.commom.client.DtkApiRequest;
import com.yami.shop.cps.commom.response.base.DtkApiResponse;
import com.yami.shop.cps.commom.response.mastertool.DtkCommodityMaterialsResponse;
import com.yami.shop.cps.commom.utils.ObjectUtil;
import com.yami.shop.cps.commom.utils.RequiredCheck;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
import java.util.Map;
/**
 * 商品精推素材请求参数实体
 *
 * @author 1
 * @date 2021/07/07 14:27
 */
@Getter
@Setter
public class DtkCommodityMaterialsRequest implements DtkApiRequest<DtkApiResponse<List<DtkCommodityMaterialsResponse>>> {
    @ApiModelProperty(value = "版本号", example = "v1.0.0")
    private String version = "1.0.0";
    @RequiredCheck
    @ApiModelProperty(value = "大淘客商品id或联盟商品id")
    private String id;
    @ApiModelProperty("商品精推素材转链请求path")
    private final String requestPath = "/goods/material/list";
    @Override
    public Map<String, String> getTextParams() throws IllegalAccessException {
        return ObjectUtil.objToMap(this);
    }
    @Override
    public String apiVersion() {
        return this.version;
    }
    @Override
    public TypeReference<DtkApiResponse<List<DtkCommodityMaterialsResponse>>> responseType() {
        return new TypeReference<DtkApiResponse<List<DtkCommodityMaterialsResponse>>>() {
        };
    }
    @Override
    public String requestUrl() {
        return this.requestPath;
    }
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkCouponQueryRequest.java
New file
@@ -0,0 +1,52 @@
package com.yami.shop.cps.commom.request.mastertool;
import com.fasterxml.jackson.core.type.TypeReference;
import com.yami.shop.cps.commom.client.DtkApiRequest;
import com.yami.shop.cps.commom.response.base.DtkApiResponse;
import com.yami.shop.cps.commom.response.mastertool.DtkCouponQueryResponse;
import com.yami.shop.cps.commom.utils.ObjectUtil;
import com.yami.shop.cps.commom.utils.RequiredCheck;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.Map;
/**
 * 优惠券查询请求参数实体
 *
 * @author 1
 * @date 2021/07/07 14:27
 */
@Getter
@Setter
public class DtkCouponQueryRequest implements DtkApiRequest<DtkApiResponse<DtkCouponQueryResponse>> {
    @ApiModelProperty(value = "版本号", example = "v1.0.0")
    private String version = "1.0.0";
    @RequiredCheck
    @ApiModelProperty(value = "二合一链接,淘口令,或同时输入商品+优惠券链接")
    private String content;
    @ApiModelProperty("优惠券查询请求path")
    private final String requestPath = "/dels/taobao/kit/coupon/get-coupon-info";
    @Override
    public Map<String, String> getTextParams() throws IllegalAccessException {
        return ObjectUtil.objToMap(this);
    }
    @Override
    public String apiVersion() {
        return this.version;
    }
    @Override
    public TypeReference<DtkApiResponse<DtkCouponQueryResponse>> responseType() {
        return new TypeReference<DtkApiResponse<DtkCouponQueryResponse>>() {
        };
    }
    @Override
    public String requestUrl() {
        return this.requestPath;
    }
}
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkCreatTaokoulingRequest.java
New file
@@ -0,0 +1,61 @@
package com.yami.shop.cps.commom.request.mastertool;
import com.fasterxml.jackson.core.type.TypeReference;
import com.yami.shop.cps.commom.client.DtkApiRequest;
import com.yami.shop.cps.commom.response.base.DtkApiResponse;
import com.yami.shop.cps.commom.response.mastertool.DtkCreatTaokoulingResponse;
import com.yami.shop.cps.commom.utils.ObjectUtil;
import com.yami.shop.cps.commom.utils.RequiredCheck;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.TreeMap;
/**
 * 淘口令生成请求参数实体
 *
 * @author 1
 * @date 2020/11/10 18:05
 */
@Getter
@Setter
public class DtkCreatTaokoulingRequest implements DtkApiRequest<DtkApiResponse<DtkCreatTaokoulingResponse>> {
    @ApiModelProperty(value = "版本号", example = "v1.0.0")
    private String version = "v1.0.0";
    @RequiredCheck
    @ApiModelProperty(value = "口令弹框内容,长度大于5个字符", required = true)
    private String text;
    @RequiredCheck
    @ApiModelProperty(value = "口令跳转目标页,如:https://uland.taobao" +
            ".com/,必须以https开头,可以是二合一链接、长链接、短链接等各种淘宝高佣链接;支持渠道备案链接。该参数需要进行UrlEncode编码后传入", required = true)
    private String url;
    @ApiModelProperty(value = "口令弹框logoURL")
    private String logo;
    @ApiModelProperty(value = "生成口令的淘宝用户ID,非必传参数")
    private String userId;
    @ApiModelProperty("淘口令生成请求path")
    private final String requestPath = "/tb-service/creat-taokouling";
    @Override
    public TypeReference<DtkApiResponse<DtkCreatTaokoulingResponse>> responseType() {
        return new TypeReference<DtkApiResponse<DtkCreatTaokoulingResponse>>() {
        };
    }
    @Override
    public TreeMap<String, String> getTextParams() throws IllegalAccessException {
        return ObjectUtil.objToMap(this);
    }
    @Override
    public String apiVersion() {
        return this.version;
    }
    @Override
    public String requestUrl() {
        return this.requestPath;
    }
}
Diff truncated after the above file
yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkCzmfTransformLinkRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkFirstOrderGiftMoneyRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkGetCollectionListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkGetOrderDetailsRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkGetOwnerGoodsRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkGetPrivilegeLinkRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkGetSuperCategoryRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkGoodsCommentListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkJdBatchTransformLinkRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkJdCommodityTransformLinkRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkJdLinkAnalysisRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkJdOrderQueryRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkJdOrderQueryV2Request.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkMergeRedEnvelopesRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkParseContentRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkParseTaokoulingRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkPddTransformLinkRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkShopConvertRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkTbCashGiftRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/DtkTwdToTwdRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/mastertool/ShearPlateDistinguishRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkGoodsDetailsRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkGoodsListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkJdCommodityDetailsRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkNewestGoodsRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkPddGoodsDetailsRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkPullGoodsByTimeRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/putstorage/DtkStaleGoodsByTimeRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkGetDtkSearchGoodsRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkGetTbServiceRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkGetTop100Request.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkHotSearchListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkJdGoodsTypeRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkJdUnionQueryRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkListSuperGoodsRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkPddGoodsTypeRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkPddOrderIncrementSearchRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkPddUnionQueryRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkSearchSuggestionRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkTbkScPunishOrderGetRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/search/DtkTbkScRelationRefundRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkActivityCatalogueRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkActivityGoodsListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkAlbumListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkBigBrandDiscountRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkCarouselMapResponseRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkCatalogueRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkDdqGoodsListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkExclusiveGoodsListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkExplosiveGoodsListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkFriendsCircleListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetBrandGoodsListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetBrandListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetColumnListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetHalfPriceDayRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetRankListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetRankingListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkGetTbTopicListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkHighCommissionSelectedRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkHistoricalNewLowCommodityRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkJdCommodityDiscountPriceRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkJdNewYearCommodityRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkJdOneDollarPurchaseOrderInquiryRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkListSimilerGoodsByOpenRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkLiveMaterialGoodsListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkMostPopularCommodityListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkNineFreeShippingRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkOpGoodsListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkPopularAnchorCommendRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkPriceTrendRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkRealTimeListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkSingleAlbumCommodityRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkSubdivisionCategoryListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkSuperDiscountGoodsRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkTipOffRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/DtkTopicGoodsListRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/subranking/DtkGetRankingListBaseRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/subranking/DtkGetRankingListByHotSearchRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/subranking/DtkGetRankingListByHotWordRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/subranking/DtkGetRankingListByHotWordUpRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/subranking/DtkGetRankingListByReBuyRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/request/special/subranking/DtkGetRankingListByTimeWholeHotRequest.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/DtkSingleAlbumCommodityResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/base/DtkApiResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/base/DtkDiffPageResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/base/DtkPageResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/base/DtkSearchPageResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkActivityLinkResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkCommodityMaterialsResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkCouponQueryResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkCreatTaokoulingResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkCzmfTransformLinkResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkFirstOrderGiftMoneyItemResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkFirstOrderGiftMoneyResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetCollectionListItemResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetOrderDetailsResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetOrderDetailsResultsItemsResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetOrderDetailsResultsResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetOwnerGoodsItemResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetPrivilegeLinkResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetSuperCategoryResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGetSuperCategorySubResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkGoodsCommentListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkJdBatchTransformLinkResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkJdCommodityTransformLinkResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkJdLinkAnalysisResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkJdOrderQueryResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkJdOrderQueryV2Response.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkMergeRedEnvelopesResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkParseContentOriginInfoResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkParseContentResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkPddTransformLinkResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkShopConvertResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkTbCashGiftResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/DtkTwdToTwdResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/MtOrderResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/mastertool/ShearPlateDistinguishResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkBaseItemResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkGoodsDetailsResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkGoodsListItemResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkJdCommodityDetailsResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkNewestGoodsResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkPddGoodsDetailsResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/putstorage/DtkStaleGoodsByTimeResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkGetDtkSearchGoodsResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkGetDtkSearchGoodsResponse1.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkGetTbServiceImagesResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkGetTbServiceResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkGetTop100Response.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkHotSearchListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkJdGoodsTypeResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkJdUnionQueryResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkListSuperGoodsResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkPddGoodsTypeResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkPddOrderIncrementSearchResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkPddUnionQueryResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkSearchSuggestionResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkTbkScPunishOrderGetResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/search/DtkTbkScRelationRefundResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkActivityCatalogueResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkActivityGoodsListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkAlbumListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkBigBrandDiscountResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkCarouselMapResponseResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkCatalogueResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkDdqGoodsListItemResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkDdqGoodsListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkDdqRoundListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkExclusiveGoodsListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkFriendsCircleListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetBrandGoodsListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetBrandListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetColumnListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetHalfPriceDayPriceItemResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetHalfPriceDayPriceResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetHalfPriceDayResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetHalfPriceDaySessionResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetRankingListMergeResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetTbTopicListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetVideoGoodsCategoryResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkGetVideoGoodsListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkHighCommissionSelectedResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkHistoricalNewLowCommodityResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkJdCommodityDiscountPriceResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkJdNewYearCommodityResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkJdOneDollarPurchaseOrderInquiryResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkListSimilerGoodsByOpenResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkLiveMaterialGoodsListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkMostPopularCommodityListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkNineFreeShippingResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkOpGoodsListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkPopularAnchorCommendResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkPopularGoodsListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkPriceTrendHistoricalPriceResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkPriceTrendResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkRealTimeListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkSubdivisionCategoryListResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkSuperDiscountGoodsResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/DtkTipOffResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkGetHotWordRankingResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkGetRankingListByHotSearchResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkGetRankingListByHotWordResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkGetRankingListByHotWordUpResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkGetRankingListByReBuyResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkGetRankingListByTimeWholeHotResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/response/special/subranking/DtkRankingBaseResponse.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsDdCategoryService.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsDdOrderService.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsJdCategoryService.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsJdOrderService.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsJtkOrderService.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsMtActitvityService.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsMtOrderService.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsOrderService.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/CpsShopService.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsDdCategoryServiceImpl.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsDdOrderServiceImpl.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsJdCategoryServiceImpl.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsJdOrderServiceImpl.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsJtkOrderServiceImpl.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsMtActitvityServiceImpl.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsMtOrderServiceImpl.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsOrderServiceImpl.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/service/impl/CpsShopServiceImpl.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/AESUtils.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/Assert.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/DTKUtils.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/JsonUtil.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/JtkUtils.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/MTUtils.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/ObjectUtil.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/PddUtils.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/RequiredCheck.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/SignMd5Util.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/SignUtils.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/utils/TBUtils.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/vo/JingDongVo.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/vo/JtkVo.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/vo/MtfxlmVo.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/vo/MtlmVo.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/vo/PddVo.java yami-shop-cps/yami-shop-cps-common/src/main/java/com/yami/shop/cps/commom/vo/TaoBaoVo.java yami-shop-cps/yami-shop-cps-common/src/main/resources/META-INF/MANIFEST.MF yami-shop-cps/yami-shop-cps-platform/pom.xml yami-shop-cps/yami-shop-cps-platform/src/main/java/com/yami/shop/cps/platform/config/SwaggerConfiguration.java yami-shop-cps/yami-shop-cps-platform/src/main/java/com/yami/shop/cps/platform/controller/CpsController.java yami-shop-delivery/pom.xml yami-shop-delivery/yami-shop-delivery-api/pom.xml yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/config/SwaggerConfiguration.java yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/controller/MyDeliveryController.java yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/controller/MyStationOrderController.java yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/controller/OrderSelfStationController.java yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/controller/StationController.java yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/listener/CheckAddrListener.java yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/listener/GetUserStationListener.java yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/listener/SubmitOrderListener.java yami-shop-delivery/yami-shop-delivery-api/src/main/java/com/yami/shop/delivery/api/manager/DeliveryOrderManager.java yami-shop-delivery/yami-shop-delivery-common/pom.xml yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/constant/TransportFreeType.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/DeliveryOrderItemMapper.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/DeliveryOrderMapper.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/OrderSelfStationMapper.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/SameCityMapper.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/TranscityFreeMapper.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/TranscityMapper.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/TransfeeFreeMapper.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/TransfeeMapper.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/dao/TransportMapper.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/listener/SameCityListener.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/DeliveryOrder.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/DeliveryOrderItem.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/OrderSelfStation.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/SameCity.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/Transcity.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/TranscityFree.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/Transfee.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/TransfeeFree.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/model/Transport.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/param/DeliveryOrderItemParam.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/param/DvyOrderParam.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/param/OrderItemParam.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/param/OrderParam.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/param/StationParam.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/DeliveryOrderItemService.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/DeliveryOrderService.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/OrderSelfStationService.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/SameCityService.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/TranscityFreeService.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/TranscityService.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/TransfeeFreeService.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/TransfeeService.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/TransportManagerService.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/TransportService.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/DeliveryOrderItemServiceImpl.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/DeliveryOrderServiceImpl.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/OrderSelfStationServiceImpl.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/SameCityServiceImpl.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/TranscityFreeServiceImpl.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/TranscityServiceImpl.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/TransfeeFreeServiceImpl.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/TransfeeServiceImpl.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/TransportManagerServiceImpl.java yami-shop-delivery/yami-shop-delivery-common/src/main/java/com/yami/shop/delivery/common/service/impl/TransportServiceImpl.java yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/DeliveryOrderItemMapper.xml yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/DeliveryOrderMapper.xml yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/OrderSelfStationMapper.xml yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/SameCityMapper.xml yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/TranscityFreeMapper.xml yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/TranscityMapper.xml yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/TransfeeFreeMapper.xml yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/TransfeeMapper.xml yami-shop-delivery/yami-shop-delivery-common/src/main/resources/mapper/TransportMapper.xml yami-shop-delivery/yami-shop-delivery-multishop/pom.xml yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/config/SwaggerConfiguration.java yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/controller/OrderDeliveryController.java yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/controller/SameCityController.java yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/controller/StationController.java yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/controller/TransportController.java yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/listener/GetTransportNamesListener.java yami-shop-delivery/yami-shop-delivery-multishop/src/main/java/com/yami/shop/delivery/multishop/listener/OrderChangeAddrListener.java yami-shop-delivery/yami-shop-delivery-platform/pom.xml yami-shop-delivery/yami-shop-delivery-platform/src/main/java/com/yami/shop/delivery/platform/config/SwaggerConfiguration.java yami-shop-delivery/yami-shop-delivery-platform/src/main/java/com/yami/shop/delivery/platform/controller/OrderDeliveryController.java yami-shop-delivery/yami-shop-delivery-platform/src/main/java/com/yami/shop/delivery/platform/controller/StationController.java yami-shop-delivery/yami-shop-delivery-platform/src/main/java/com/yami/shop/delivery/platform/controller/TransportController.java