diff --git a/coolstore-partner-common/src/main/java/com/cool/store/enums/ErrorCodeEnum.java b/coolstore-partner-common/src/main/java/com/cool/store/enums/ErrorCodeEnum.java index 90a7a1587..5a220557a 100644 --- a/coolstore-partner-common/src/main/java/com/cool/store/enums/ErrorCodeEnum.java +++ b/coolstore-partner-common/src/main/java/com/cool/store/enums/ErrorCodeEnum.java @@ -68,6 +68,14 @@ public enum ErrorCodeEnum { IMPROVE_USER_INFO(1021086,"请联系管理员,完善用户信息!",null), PASSWORD_ERROR(1021087, "密码输入错误",null), PASSWORD_ERROR_MULTI(1021088, "密码错误{0}次,请使用验证码登录",null), + + MOBILE_NOT_MATCH(1023001, "修改失败,手机号与当前用户不匹配",null), + SMS_CODE_EXPIRE(1023002, "验证码已过期!",null), + SMS_CODE_ERROR(1023003, "验证码错误!",null), + SEND_SMS_LIMIT_COUNT(1023004, "短信发送失败,今日发送短信已达上限",null), + NONSUPPORT_MOBILE(1023005, "暂不支持的手机号格式", null), + SMS_CODE_MISSING(1023006, "验证码缺失!",null), + //红圈通 HQT_SHOP_DECORATION_ATTRIBUTES(1022000, "获取红圈通装修属性错误", null), HQT_PARAMS_ERROR(1022001, "构建红圈通请求参数错误", null), diff --git a/coolstore-partner-common/src/main/java/com/cool/store/enums/LoginTypeEnum.java b/coolstore-partner-common/src/main/java/com/cool/store/enums/LoginTypeEnum.java index f7b95f109..dad1a972f 100644 --- a/coolstore-partner-common/src/main/java/com/cool/store/enums/LoginTypeEnum.java +++ b/coolstore-partner-common/src/main/java/com/cool/store/enums/LoginTypeEnum.java @@ -16,6 +16,7 @@ import lombok.Getter; public enum LoginTypeEnum { PASSWORD("账号密码", "passwordLoginServiceImpl"), + SMS("短信验证码","smsLoginServiceImpl"), ; diff --git a/coolstore-partner-common/src/main/java/com/cool/store/enums/SmsCodeTypeEnum.java b/coolstore-partner-common/src/main/java/com/cool/store/enums/SmsCodeTypeEnum.java index b439c20e5..fdeeda5ac 100644 --- a/coolstore-partner-common/src/main/java/com/cool/store/enums/SmsCodeTypeEnum.java +++ b/coolstore-partner-common/src/main/java/com/cool/store/enums/SmsCodeTypeEnum.java @@ -4,14 +4,14 @@ package com.cool.store.enums; public enum SmsCodeTypeEnum { LOGIN("SMS_220325070","验证码登录", 10 * 60), - FORGOT_PWD("SMS_220325070","忘记密码", 10 * 60), +// FORGOT_PWD("SMS_220325070","忘记密码", 10 * 60), MODIFY_PWD("SMS_220325070","修改密码", 10 * 60), IMPROVE_INFO("SMS_220325070","完善用户信息", 10 * 60), USER_REGISTER("SMS_220325070","用户注册", 10 * 60), ENTERPRISE_REGISTER("SMS_220325070","企业注册", 10 * 60), - LOGIN2("SMS_232163403","验证码登录", 10 * 60), - + LOGIN2("SMS_498720063","验证码登录", 10 * 60), + LOGIN_INTERNATIONAL("SMS_474876096", "国际验证码登录", 10 * 60), diff --git a/coolstore-partner-common/src/main/java/com/cool/store/enums/sms/SmsZoneEnum.java b/coolstore-partner-common/src/main/java/com/cool/store/enums/sms/SmsZoneEnum.java new file mode 100644 index 000000000..ec62d9b36 --- /dev/null +++ b/coolstore-partner-common/src/main/java/com/cool/store/enums/sms/SmsZoneEnum.java @@ -0,0 +1,68 @@ +package com.cool.store.enums.sms; + +import cn.hutool.core.lang.PatternPool; +import cn.hutool.core.lang.Validator; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.PhoneUtil; +import com.cool.store.enums.SmsCodeTypeEnum; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; + +import java.util.regex.Pattern; + +/** + * describe: 短信手机区号类型 + * + * @author wangff + * @date 2024/11/8 + */ +@Getter +@AllArgsConstructor +public enum SmsZoneEnum { + INDONESIA("+62", "印度尼西亚", SmsCodeTypeEnum.LOGIN_INTERNATIONAL.getTemplateCode(), Pattern.compile("\\d{10,12}")), + + MALAYSIA("+60", "马来西亚", SmsCodeTypeEnum.LOGIN_INTERNATIONAL.getTemplateCode(), Pattern.compile("\\d{6,12}")), + + CHINA("+86", "中国", SmsCodeTypeEnum.LOGIN2.getTemplateCode(), PatternPool.MOBILE), + ; + + /** + * 区号 + */ + private final String code; + + /** + * 描述 + */ + private final String msg; + + /** + * 短信模板code + */ + private final String templateCode; + + /** + * 手机号格式 + */ + private final Pattern mobilePattern; + + /** + * 根据手机号获取枚举类型 + * @param mobile 手机号 + * @return 短信手机区号类型 + */ + public static SmsZoneEnum getByMobile(String mobile) { + if (StringUtils.isBlank(mobile)) { + return null; + } + if (PhoneUtil.isMobile(mobile)) { + return CHINA; + } + String[] split = mobile.split(" "); + if (split.length < 2) { + return null; + } + return ArrayUtil.firstMatch(v -> split[0].startsWith(v.getCode()) && Validator.isMatchRegex(v.getMobilePattern(), split[1]), values()); + } +} diff --git a/coolstore-partner-common/src/main/java/com/cool/store/utils/HttpHelper.java b/coolstore-partner-common/src/main/java/com/cool/store/utils/HttpHelper.java new file mode 100644 index 000000000..b4d846abb --- /dev/null +++ b/coolstore-partner-common/src/main/java/com/cool/store/utils/HttpHelper.java @@ -0,0 +1,27 @@ +package com.cool.store.utils; + +import javax.servlet.http.HttpServletRequest; + +/** + *
+ * + *
+ * + * @author wangff + * @since 2026/3/2 + */ +public class HttpHelper { + public static String getIpAddr(HttpServletRequest request) { + 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(); + } + return ip; + } +} diff --git a/coolstore-partner-common/src/main/java/com/cool/store/utils/MobileUtil.java b/coolstore-partner-common/src/main/java/com/cool/store/utils/MobileUtil.java new file mode 100644 index 000000000..b7737c571 --- /dev/null +++ b/coolstore-partner-common/src/main/java/com/cool/store/utils/MobileUtil.java @@ -0,0 +1,72 @@ +package com.cool.store.utils; + +import cn.hutool.core.util.ObjectUtil; +import com.cool.store.enums.ErrorCodeEnum; +import com.cool.store.enums.sms.SmsZoneEnum; +import com.cool.store.exception.ServiceException; +import org.apache.commons.lang3.StringUtils; + +/** + * describe: 手机号工具类 + * + * @author wangff + * @date 2024/11/8 + */ +public class MobileUtil { + + /** + * 根据手机号获取短信手机区号类型枚举 + * @param mobile 手机号 + * @return 短信手机区号类型枚举 + */ + public static String getSmsTemplateCode(String mobile) { + SmsZoneEnum smsZoneEnum = SmsZoneEnum.getByMobile(mobile); + if (ObjectUtil.isNull(smsZoneEnum)) { + throw new ServiceException(ErrorCodeEnum.NONSUPPORT_MOBILE); + } + return smsZoneEnum.getTemplateCode(); + } + + /** + * 去除手机号中的+号和空格 + * @param mobile 手机号 + * @return 手机号 + */ + public static String transNoPlusAndBlank(String mobile) { + if (StringUtils.isBlank(mobile)) { + return mobile; + } + String[] array = StringUtils.split(mobile, ' '); + if (array.length < 2) { + return mobile; + } + return array[0].substring(1).trim() + array[1].trim(); + } + + /** + * 校验手机号格式 + * @param mobile 手机号 + * @return 格式是否正确 + */ + public static boolean validateMobile(String mobile) { + SmsZoneEnum smsZoneEnum = SmsZoneEnum.getByMobile(mobile); + return ObjectUtil.isNotNull(smsZoneEnum); + } + + /** + * 手机号统一存储格式 + *+ * 国内手机号去除86/+86,国外手机号格式不变 + *
+ * @param mobile 手机号 + * @return 格式化后手机号 + */ + public static String unifyMobile(String mobile) { + SmsZoneEnum smsZoneEnum = SmsZoneEnum.getByMobile(mobile); + if (SmsZoneEnum.CHINA.equals(smsZoneEnum) && (mobile.startsWith("+86") || mobile.startsWith("86"))) { + mobile = mobile.substring(mobile.indexOf("86") + 2).trim(); + } + return mobile; + } + +} diff --git a/coolstore-partner-dao/src/main/java/com/cool/store/mapper/EnterpriseUserMapper.java b/coolstore-partner-dao/src/main/java/com/cool/store/mapper/EnterpriseUserMapper.java index ae0c77f3d..1a6504221 100644 --- a/coolstore-partner-dao/src/main/java/com/cool/store/mapper/EnterpriseUserMapper.java +++ b/coolstore-partner-dao/src/main/java/com/cool/store/mapper/EnterpriseUserMapper.java @@ -113,4 +113,8 @@ public interface EnterpriseUserMapper { */ @PlatformDB UserLoginDO getUserLoginByUnionid(@Param("unionid") String unionid); + + @PlatformDB + Integer modifyPasswordByMobile(@Param("mobile") String mobile, @Param("password") String password); + } \ No newline at end of file diff --git a/coolstore-partner-dao/src/main/resources/mapper/EnterpriseUserMapper.xml b/coolstore-partner-dao/src/main/resources/mapper/EnterpriseUserMapper.xml index 5a019939f..c9f3cd704 100644 --- a/coolstore-partner-dao/src/main/resources/mapper/EnterpriseUserMapper.xml +++ b/coolstore-partner-dao/src/main/resources/mapper/EnterpriseUserMapper.xml @@ -241,4 +241,8 @@ FROM enterprise_user WHERE unionid = #{unionid} AND active = true + ++ * 用户 + *
+ * + * @author wangff + * @since 2026/3/2 + */ +public interface EnterpriseUserService { + + /** + * 修改密码 + */ + ResponseResult modifyPassword(ModifyPasswordDTO param); +} diff --git a/coolstore-partner-service/src/main/java/com/cool/store/service/enterprise/impl/EnterpriseUserServiceImpl.java b/coolstore-partner-service/src/main/java/com/cool/store/service/enterprise/impl/EnterpriseUserServiceImpl.java new file mode 100644 index 000000000..5b12cb0f7 --- /dev/null +++ b/coolstore-partner-service/src/main/java/com/cool/store/service/enterprise/impl/EnterpriseUserServiceImpl.java @@ -0,0 +1,49 @@ +package com.cool.store.service.enterprise.impl; + +import com.cool.store.constants.CommonConstants; +import com.cool.store.dto.login.ModifyPasswordDTO; +import com.cool.store.enums.ErrorCodeEnum; +import com.cool.store.enums.SmsCodeTypeEnum; +import com.cool.store.mapper.EnterpriseUserMapper; +import com.cool.store.response.ResponseResult; +import com.cool.store.service.enterprise.EnterpriseUserService; +import com.cool.store.utils.Md5Utils; +import com.cool.store.utils.RedisUtilPool; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + *+ * 用户 + *
+ * + * @author wangff + * @since 2026/3/2 + */ +@Service(value = "enterpriseUserService") +@Slf4j +public class EnterpriseUserServiceImpl implements EnterpriseUserService { + @Resource + private RedisUtilPool redisUtilPool; + @Resource + private EnterpriseUserMapper enterpriseUserMapper; + + @Override + public ResponseResult modifyPassword(ModifyPasswordDTO param) { + String smsCodeKey = SmsCodeTypeEnum.MODIFY_PWD + ":" + param.getMobile(); + String smsCode = param.getSmsCode(); + String codeValue = redisUtilPool.getString(smsCodeKey); + if (StringUtils.isBlank(codeValue)) { + return ResponseResult.fail(ErrorCodeEnum.SMS_CODE_EXPIRE); + } + if (!smsCode.equals(codeValue)) { + return ResponseResult.fail(ErrorCodeEnum.SMS_CODE_ERROR); + } + enterpriseUserMapper.modifyPasswordByMobile(param.getMobile(), Md5Utils.md5(param.getPassword() + CommonConstants.USER_AUTH_KEY)); + redisUtilPool.delKey(smsCodeKey); + return ResponseResult.success(); + } +} diff --git a/coolstore-partner-service/src/main/java/com/cool/store/service/impl/CommonService.java b/coolstore-partner-service/src/main/java/com/cool/store/service/impl/CommonService.java index 05f1505b9..061934d79 100644 --- a/coolstore-partner-service/src/main/java/com/cool/store/service/impl/CommonService.java +++ b/coolstore-partner-service/src/main/java/com/cool/store/service/impl/CommonService.java @@ -118,19 +118,23 @@ public class CommonService { } public void sendSms(String poneNumber, SMSMsgEnum templateCode){ - sendSms(Arrays.asList(poneNumber), templateCode, null); + sendSms(Arrays.asList(poneNumber), templateCode.getTemplateCode(), null); } public void sendSms(String poneNumber, SMSMsgEnum templateCode, Map
@@ -63,6 +65,9 @@ public abstract class LoginBaseService implements LoginStrategy {
}
}
EnterpriseUserDO enterpriseUserDO = enterpriseUserDAO.selectByMobile(param.getMobile());
+ if (Objects.isNull(enterpriseUserDO)) {
+ throw new ServiceException(ErrorCodeEnum.PARTNER_MOBILE_INCORRECT);
+ }
UserLoginDO userLoginDO = enterpriseUserDAO.getUserLoginByUnionid(enterpriseUserDO.getUnionid());
return userLogin(param, userLoginDO);
}
diff --git a/coolstore-partner-service/src/main/java/com/cool/store/service/login/impl/SmsLoginServiceImpl.java b/coolstore-partner-service/src/main/java/com/cool/store/service/login/impl/SmsLoginServiceImpl.java
new file mode 100644
index 000000000..20a837f3d
--- /dev/null
+++ b/coolstore-partner-service/src/main/java/com/cool/store/service/login/impl/SmsLoginServiceImpl.java
@@ -0,0 +1,48 @@
+package com.cool.store.service.login.impl;
+
+import com.cool.store.dto.login.UserLoginDTO;
+import com.cool.store.entity.login.UserLoginDO;
+import com.cool.store.enums.ErrorCodeEnum;
+import com.cool.store.enums.SmsCodeTypeEnum;
+import com.cool.store.response.ResponseResult;
+import com.cool.store.service.login.LoginBaseService;
+import com.cool.store.utils.RedisUtilPool;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+/**
+ * @author zhangchenbiao
+ * @FileName: SmsLoginService
+ * @Description: 验证码登录实现类
+ * @date 2021-07-16 11:45
+ */
+@Service("smsLoginServiceImpl")
+@Slf4j
+public class SmsLoginServiceImpl extends LoginBaseService {
+
+ @Resource
+ private RedisUtilPool redisUtilPool;
+
+ @Override
+ public ResponseResult userLogin(UserLoginDTO param, UserLoginDO userLoginDO) {
+ String mobile = param.getMobile();
+ String smsCode = param.getSmsCode();
+ if (StringUtils.isBlank(smsCode)) {
+ return ResponseResult.fail(ErrorCodeEnum.SMS_CODE_MISSING);
+ }
+ String smsCodeKey = SmsCodeTypeEnum.LOGIN + ":" + mobile;
+ String code = redisUtilPool.getString(smsCodeKey);
+ if (StringUtils.isBlank(code)) {
+ return ResponseResult.fail(ErrorCodeEnum.SMS_CODE_EXPIRE);
+ }
+ if (!smsCode.equals(code)) {
+ return ResponseResult.fail(ErrorCodeEnum.SMS_CODE_ERROR);
+ }
+ redisUtilPool.delKey(smsCodeKey);
+ return ResponseResult.success(getUserLoginInfo(userLoginDO));
+ }
+
+}
diff --git a/coolstore-partner-service/src/main/java/com/cool/store/service/sms/AliyunSmsService.java b/coolstore-partner-service/src/main/java/com/cool/store/service/sms/AliyunSmsService.java
new file mode 100644
index 000000000..42d0c23c7
--- /dev/null
+++ b/coolstore-partner-service/src/main/java/com/cool/store/service/sms/AliyunSmsService.java
@@ -0,0 +1,21 @@
+package com.cool.store.service.sms;
+
+
+import com.cool.store.enums.SmsCodeTypeEnum;
+import com.cool.store.response.ResponseResult;
+
+/**
+ * @author zhangchenbiao
+ * @FileName: AliyunSmsService
+ * @Description: 阿里云短信
+ * @date 2021-07-23 11:33
+ */
+public interface AliyunSmsService {
+
+ /**
+ * 发送短信
+ * @param mobile 手机号
+ * @param codeType 验证码类型
+ */
+ ResponseResult sendSmsCode(String mobile, SmsCodeTypeEnum codeType);
+}
diff --git a/coolstore-partner-service/src/main/java/com/cool/store/service/sms/impl/AliyunSmsServiceImpl.java b/coolstore-partner-service/src/main/java/com/cool/store/service/sms/impl/AliyunSmsServiceImpl.java
new file mode 100644
index 000000000..341ce206a
--- /dev/null
+++ b/coolstore-partner-service/src/main/java/com/cool/store/service/sms/impl/AliyunSmsServiceImpl.java
@@ -0,0 +1,48 @@
+package com.cool.store.service.sms.impl;
+
+import com.cool.store.enums.SmsCodeTypeEnum;
+import com.cool.store.response.ResponseResult;
+import com.cool.store.service.impl.CommonService;
+import com.cool.store.service.sms.AliyunSmsService;
+import com.cool.store.utils.MobileUtil;
+import com.cool.store.utils.RedisUtilPool;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author zhangchenbiao
+ * @FileName: AliyunSmsServiceImpl
+ * @Description: 发送短信
+ * @date 2021-07-23 11:37
+ */
+@Service
+@Slf4j
+public class AliyunSmsServiceImpl implements AliyunSmsService {
+
+ @Resource
+ private RedisUtilPool redisUtilPool;
+ @Resource
+ private CommonService commonService;
+
+ @Override
+ public ResponseResult sendSmsCode(String mobile, SmsCodeTypeEnum codeType) {
+ String smsCodeKey = codeType + ":" + mobile;
+ String smsCode = getRandNum();
+ String templateCode = MobileUtil.getSmsTemplateCode(mobile);
+
+ Map
* 登录 前端控制器
@@ -25,17 +38,24 @@ import org.springframework.web.bind.annotation.*;
@RequestMapping("/pc/v3/login")
@RequiredArgsConstructor
public class LoginController {
- private final LoginBaseService loginBaseService;
+ @Resource(name = "passwordLoginServiceImpl")
+ private LoginBaseService loginBaseService;
+ private final EnterpriseUserService enterpriseUserService;
+ private final RedisUtilPool redisUtilPool;
+ private final AliyunSmsService aliyunSmsService;
- @ApiOperation("账号密码登录")
+ private final int SEND_SMS_LIMIT_COUNT = 10;
+ private final int SEND_SMS_IP_LIMIT_COUNT = 100;
+
+ @ApiOperation("登录")
@PostMapping("/accountLogin")
- public ResponseResult