diff --git a/accompany-admin/accompany-admin-service/pom.xml b/accompany-admin/accompany-admin-service/pom.xml index 79a4d362a..73beaf9cc 100644 --- a/accompany-admin/accompany-admin-service/pom.xml +++ b/accompany-admin/accompany-admin-service/pom.xml @@ -76,6 +76,12 @@ sa-token-dao-redis-jackson ${sa-token.version} + + software.amazon.awssdk + sesv2 + 2.30.38 + compile + \ No newline at end of file diff --git a/accompany-admin/accompany-admin-service/src/main/java/com/accompany/admin/service/api/MyApiService.java b/accompany-admin/accompany-admin-service/src/main/java/com/accompany/admin/service/api/MyApiService.java index 5554f8018..f96a48e62 100644 --- a/accompany-admin/accompany-admin-service/src/main/java/com/accompany/admin/service/api/MyApiService.java +++ b/accompany-admin/accompany-admin-service/src/main/java/com/accompany/admin/service/api/MyApiService.java @@ -31,6 +31,7 @@ import com.accompany.business.service.room.RoomSendRankingService; import com.accompany.business.service.room.RoomService; import com.accompany.business.service.user.UsersService; import com.accompany.business.vo.RoomVo; +import com.accompany.common.constant.AppEnum; import com.accompany.common.redis.RedisKey; import com.accompany.common.status.BusiStatus; import com.accompany.common.utils.CommonUtil; @@ -46,6 +47,7 @@ import com.accompany.core.service.account.AccountService; import com.accompany.core.service.common.JedisService; import com.accompany.core.service.region.RegionService; import com.accompany.core.vo.UserLevelVo; +import com.accompany.email.config.AwsSesConfig; import com.accompany.payment.apple.ApplePublisher; import com.accompany.payment.iospay.JWTTranscationInfoPayload; import com.accompany.payment.model.ChargeRecord; @@ -56,7 +58,6 @@ import com.accompany.sharding.model.GiftSendRecord; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.google.common.collect.Lists; @@ -64,9 +65,24 @@ import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.MessagingException; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.sesv2.model.Body; +import software.amazon.awssdk.services.sesv2.model.Content; +import software.amazon.awssdk.services.sesv2.model.Destination; +import software.amazon.awssdk.services.sesv2.model.EmailContent; +import software.amazon.awssdk.services.sesv2.model.Message; +import software.amazon.awssdk.services.sesv2.model.SendEmailRequest; +import software.amazon.awssdk.services.sesv2.model.SesV2Exception; +import software.amazon.awssdk.services.sesv2.SesV2Client; + import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; @@ -729,4 +745,81 @@ public class MyApiService { weekGuildStatMapper.delete(null); weekGuildStatMapper.insert(lastWeekGuildStatList); } + + public void testMail() { + SesV2Client client = SpringContextHolder.getBean(SesV2Client.class); + + String appName = AppEnum.getCurApp().getValue(); + String logoUrl = "https://" + AppEnum.getCurApp().getResourceDomain() + "/" + appName + ".png"; + + String sender = "Verification Code "; + String recipient = "842328916@qq.com"; + String subject = String.format("%s verification code", appName); + + // The HTML body of the email. + String bodyHTML = + String.format( + "\n" + + "\n" + + " \n" + + "

%s verification code

\n" + + "
\n" + + " **123456**\n" + + "
\n" + + "

Expires in: 10 minutes

\n" + + "\n" + + "", logoUrl, appName); + + try { + send(client, sender, recipient, subject, bodyHTML); + client.close(); + System.out.println("Done"); + + } catch (MessagingException e) { + e.getStackTrace(); + } + } + + private void send(SesV2Client client, String sender, String recipient, String subject, String bodyHTML){ + Destination destination = Destination.builder() + .toAddresses(recipient) + .build(); + + Content content = Content.builder() + .data(bodyHTML) + .build(); + + Content sub = Content.builder() + .data(subject) + .build(); + + Body body = Body.builder() + .html(content) + .build(); + + Message msg = Message.builder() + .subject(sub) + .body(body) + .build(); + + EmailContent emailContent = EmailContent.builder() + .simple(msg) + .build(); + + SendEmailRequest emailRequest = SendEmailRequest.builder() + .destination(destination) + .content(emailContent) + .fromEmailAddress(sender) + .build(); + + try { + System.out.println("Attempting to send an email through Amazon SES " + + "using the AWS SDK for Java..."); + client.sendEmail(emailRequest); + System.out.println("email was sent"); + + } catch (SesV2Exception e) { + System.err.println(e.awsErrorDetails().errorMessage()); + } + } } diff --git a/accompany-admin/accompany-admin-web/src/main/java/com/accompany/admin/controller/api/MyApiController.java b/accompany-admin/accompany-admin-web/src/main/java/com/accompany/admin/controller/api/MyApiController.java index 493772ba4..66ac1a4a2 100644 --- a/accompany-admin/accompany-admin-web/src/main/java/com/accompany/admin/controller/api/MyApiController.java +++ b/accompany-admin/accompany-admin-web/src/main/java/com/accompany/admin/controller/api/MyApiController.java @@ -263,4 +263,13 @@ public class MyApiController { myApiService.refreshWeekGuildStat(); return BusiResult.success(); } + + @GetMapping("/testMail") + public BusiResult testMail(Long roomId) { + if (null == roomId){ + throw new ServiceException(BusiStatus.PARAMERROR); + } + myApiService.testMail(); + return BusiResult.success(); + } } diff --git a/accompany-base/accompany-basic/accompany-basic-service/src/main/java/com/accompany/core/service/account/AccountBlockCheckService.java b/accompany-base/accompany-basic/accompany-basic-service/src/main/java/com/accompany/core/service/account/AccountBlockCheckService.java index 8b1976253..a35107e28 100644 --- a/accompany-base/accompany-basic/accompany-basic-service/src/main/java/com/accompany/core/service/account/AccountBlockCheckService.java +++ b/accompany-base/accompany-basic/accompany-basic-service/src/main/java/com/accompany/core/service/account/AccountBlockCheckService.java @@ -62,6 +62,12 @@ public class AccountBlockCheckService { return checkBlocked(phone, BlockTypeEnum.BLOCK_PHONE); } + public boolean checkBlockedEmail(String email){ + if (!StringUtils.hasText(email)){ + return false; + } + return checkBlocked(email, BlockTypeEnum.BLOCK_PHONE); + } /** * 查询设备是否被封禁 diff --git a/accompany-base/accompany-core/src/main/java/com/accompany/common/constant/EmailConstant.java b/accompany-base/accompany-core/src/main/java/com/accompany/common/constant/EmailConstant.java new file mode 100644 index 000000000..062acd626 --- /dev/null +++ b/accompany-base/accompany-core/src/main/java/com/accompany/common/constant/EmailConstant.java @@ -0,0 +1,40 @@ +package com.accompany.common.constant; + +/** + * Created by PaperCut on 2018/7/23. + */ +public class EmailConstant { + + public static final int EXPIRE_MINUTE = 3; + + /** + * 短信过期时间60秒 + */ + public static final int EXPIRE_SECONDS = 60; + + /** + * 短信发送间隔时间,1分钟只能发1条 + */ + public static final int SEND_INTERVAL_SECONDS = 60; + + /** + * 验证码短信类型 + */ + public static class EmailType { + + public static final Byte REGISTER = 1;//注册 + public static final Byte LOGIN = 2; //登录 + public static final Byte RESET_LOGIN_PASSWORD = 3;//忘记登录密码 + public static final Byte BINDING_PHONE = 4; //绑定手机 + public static final Byte BINDING_ALIPAY = 5; //绑定支付宝 + public static final Byte RESET_PAY_PASSWORD = 6; //重置支付密码 + public static final Byte UNBINDING_PHONE = 7; //更换绑定手机号码 + public static final Byte CERTIFICATION = 8; //实名认证 + public static final Byte H5_BINDING_ALIPAY = 9; //h5绑定支付宝 + public static final Byte SUPER_ADMIN_LOGIN = 10; //超管登录 + public static final Byte BINDING_BANK_CARD = 11; //绑定提现银行卡 + public static final Byte H5_BINDING_BANK_CARD = 12; //h5 绑定提现银行卡 + public static final Byte AUTH_CODE = 13; // 获取手机授权码 + } + +} diff --git a/accompany-base/accompany-core/src/main/java/com/accompany/common/redis/RedisKey.java b/accompany-base/accompany-core/src/main/java/com/accompany/common/redis/RedisKey.java index a9851a6cd..407b0e790 100644 --- a/accompany-base/accompany-core/src/main/java/com/accompany/common/redis/RedisKey.java +++ b/accompany-base/accompany-core/src/main/java/com/accompany/common/redis/RedisKey.java @@ -1430,6 +1430,9 @@ public enum RedisKey { user_visitor_count, user_visitor, + + email_code, + email_send_interval, ; public String getKey() { diff --git a/accompany-base/accompany-core/src/main/java/com/accompany/core/constant/BlockTypeEnum.java b/accompany-base/accompany-core/src/main/java/com/accompany/core/constant/BlockTypeEnum.java index 65d8529e6..0f9ba379a 100644 --- a/accompany-base/accompany-core/src/main/java/com/accompany/core/constant/BlockTypeEnum.java +++ b/accompany-base/accompany-core/src/main/java/com/accompany/core/constant/BlockTypeEnum.java @@ -19,6 +19,7 @@ public enum BlockTypeEnum { BLOCK_DEVICE(3,"封禁设备","用户设备异常,请联系官方客服"), BLOCK_IP(4,"封禁IP","用户IP异常,请联系官方客服"), BLOCK_MUTE(5,"禁言",""), + BLOCK_EMAIL(2, "封禁邮箱号","用户邮箱号异常,请联系官方客服"), ; BlockTypeEnum(int value, String desc, String blockDesc){ diff --git a/accompany-base/accompany-email/accompany-email-sdk/pom.xml b/accompany-base/accompany-email/accompany-email-sdk/pom.xml new file mode 100644 index 000000000..b451a68ab --- /dev/null +++ b/accompany-base/accompany-email/accompany-email-sdk/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + com.accompany + accompany-email + 1.0.0 + + + accompany-email-sdk + jar + + + + com.accompany + accompany-core + ${revision} + + + + \ No newline at end of file diff --git a/accompany-base/accompany-email/accompany-email-sdk/src/main/java/com/accompany/email/config/AwsSesConfig.java b/accompany-base/accompany-email/accompany-email-sdk/src/main/java/com/accompany/email/config/AwsSesConfig.java new file mode 100644 index 000000000..5d7664137 --- /dev/null +++ b/accompany-base/accompany-email/accompany-email-sdk/src/main/java/com/accompany/email/config/AwsSesConfig.java @@ -0,0 +1,18 @@ +package com.accompany.email.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +@Data +@RefreshScope +@Configuration +@ConfigurationProperties(prefix = "aws.ses") +public class AwsSesConfig { + + private String accessKeyId; + private String secretAccessKey; + private String region; + +} diff --git a/accompany-base/accompany-email/accompany-email-sdk/src/main/java/com/accompany/email/config/EmailConfig.java b/accompany-base/accompany-email/accompany-email-sdk/src/main/java/com/accompany/email/config/EmailConfig.java new file mode 100644 index 000000000..0807bcc12 --- /dev/null +++ b/accompany-base/accompany-email/accompany-email-sdk/src/main/java/com/accompany/email/config/EmailConfig.java @@ -0,0 +1,18 @@ +package com.accompany.email.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +@Data +@RefreshScope +@Configuration +@ConfigurationProperties(prefix = "email") +public class EmailConfig { + + private String appName; + private String logoUrl; + private String sender; + +} diff --git a/accompany-base/accompany-email/accompany-email-sdk/src/main/java/com/accompany/email/enums/SesTypeEnum.java b/accompany-base/accompany-email/accompany-email-sdk/src/main/java/com/accompany/email/enums/SesTypeEnum.java new file mode 100644 index 000000000..4e991cc63 --- /dev/null +++ b/accompany-base/accompany-email/accompany-email-sdk/src/main/java/com/accompany/email/enums/SesTypeEnum.java @@ -0,0 +1,11 @@ +package com.accompany.email.enums; + +/** + * @author: liaozetao + * @date: 2023/8/14 15:14 + * @description: + */ +public enum SesTypeEnum { + + AWS, +} diff --git a/accompany-base/accompany-email/accompany-email-sdk/src/main/java/com/accompany/email/model/EmailRecord.java b/accompany-base/accompany-email/accompany-email-sdk/src/main/java/com/accompany/email/model/EmailRecord.java new file mode 100644 index 000000000..63a7921c8 --- /dev/null +++ b/accompany-base/accompany-email/accompany-email-sdk/src/main/java/com/accompany/email/model/EmailRecord.java @@ -0,0 +1,52 @@ +package com.accompany.email.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author yangming + * @since 2020-04-13 + * 短信记录表 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("email_record") +public class EmailRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String email; + + private String deviceId; + + private String os; + + private String channel; + + private String appVersion; + + private String model; + + private String code; + + private Integer sesType; + + private String ip; + + private String resCode; + + private String resMsg; + + private Date createTime; +} \ No newline at end of file diff --git a/accompany-base/accompany-email/accompany-email-service/pom.xml b/accompany-base/accompany-email/accompany-email-service/pom.xml new file mode 100644 index 000000000..76f9ee667 --- /dev/null +++ b/accompany-base/accompany-email/accompany-email-service/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + com.accompany + accompany-email + 1.0.0 + + + accompany-email-service + jar + + + + com.accompany + accompany-email-sdk + ${revision} + + + + + software.amazon.awssdk + sesv2 + 2.30.37 + + + + + \ No newline at end of file diff --git a/accompany-base/accompany-email/accompany-email-service/src/main/java/com/accompany/email/config/AwsSecClientConfig.java b/accompany-base/accompany-email/accompany-email-service/src/main/java/com/accompany/email/config/AwsSecClientConfig.java new file mode 100644 index 000000000..d4b521321 --- /dev/null +++ b/accompany-base/accompany-email/accompany-email-service/src/main/java/com/accompany/email/config/AwsSecClientConfig.java @@ -0,0 +1,30 @@ +package com.accompany.email.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.sesv2.SesV2Client; + +@Configuration +public class AwsSecClientConfig { + + @Autowired + private AwsSesConfig config; + + @Bean + public SesV2Client awsSecClient() { + AwsCredentialsProviderChain awsCredentialsProviderChain = AwsCredentialsProviderChain + .builder() + .addCredentialsProvider(() -> AwsBasicCredentials.create(config.getAccessKeyId(), config.getSecretAccessKey())).build(); + + Region region = Region.of(config.getRegion()); + return SesV2Client.builder() + .region(region) + .credentialsProvider(awsCredentialsProviderChain) + .build(); + } + +} diff --git a/accompany-base/accompany-email/accompany-email-service/src/main/java/com/accompany/email/mapper/EmailRecordMapper.java b/accompany-base/accompany-email/accompany-email-service/src/main/java/com/accompany/email/mapper/EmailRecordMapper.java new file mode 100644 index 000000000..9ef080a18 --- /dev/null +++ b/accompany-base/accompany-email/accompany-email-service/src/main/java/com/accompany/email/mapper/EmailRecordMapper.java @@ -0,0 +1,11 @@ +package com.accompany.email.mapper; + +import com.accompany.email.model.EmailRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @author yangming + * @since 2020-04-13 + */ +public interface EmailRecordMapper extends BaseMapper { +} \ No newline at end of file diff --git a/accompany-base/accompany-email/accompany-email-service/src/main/java/com/accompany/email/service/EmailRecordService.java b/accompany-base/accompany-email/accompany-email-service/src/main/java/com/accompany/email/service/EmailRecordService.java new file mode 100644 index 000000000..543ceda0c --- /dev/null +++ b/accompany-base/accompany-email/accompany-email-service/src/main/java/com/accompany/email/service/EmailRecordService.java @@ -0,0 +1,41 @@ +package com.accompany.email.service; + +import com.accompany.common.device.DeviceInfo; +import com.accompany.email.mapper.EmailRecordMapper; +import com.accompany.email.model.EmailRecord; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.Date; + +@Service +public class EmailRecordService extends ServiceImpl { + + /** + * 插入记录 + * @param email + * @param deviceInfo + * @param ip + * @param code + * @param type + */ + public void saveRecord(String email, DeviceInfo deviceInfo, String ip, String code, Integer type, + String resCode, String resMsg) { + EmailRecord record = new EmailRecord(); + record.setEmail(email); + if (deviceInfo != null){ + record.setDeviceId(deviceInfo.getDeviceId()); + record.setOs(deviceInfo.getOs()); + record.setModel(deviceInfo.getModel()); + record.setChannel(deviceInfo.getChannel()); + } + record.setCreateTime(new Date()); + record.setIp(ip); + record.setCode(code); + record.setSesType(type); + record.setResCode(resCode); + record.setResMsg(resMsg); + save(record); + } + +} diff --git a/accompany-base/accompany-email/accompany-email-service/src/main/java/com/accompany/email/service/EmailService.java b/accompany-base/accompany-email/accompany-email-service/src/main/java/com/accompany/email/service/EmailService.java new file mode 100644 index 000000000..bd55e86d6 --- /dev/null +++ b/accompany-base/accompany-email/accompany-email-service/src/main/java/com/accompany/email/service/EmailService.java @@ -0,0 +1,96 @@ +package com.accompany.email.service; + +import cn.hutool.core.util.StrUtil; +import com.accompany.common.constant.EmailConstant; +import com.accompany.common.device.DeviceInfo; +import com.accompany.common.redis.RedisKey; +import com.accompany.common.status.BusiStatus; +import com.accompany.common.utils.RandomUtil; +import com.accompany.common.utils.StringUtils; +import com.accompany.core.exception.ServiceException; +import com.accompany.core.service.base.BaseService; +import lombok.extern.slf4j.Slf4j; +import org.redisson.api.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import java.util.concurrent.TimeUnit; + + +/** + * @author yanhaoyu + */ +@Slf4j +@Service +public class EmailService extends BaseService { + + @Autowired + private RedissonClient redissonClient; + @Autowired + private EmailRecordService emailRecordService; + + public void sendEmailCode(String emailAddress, Integer type, DeviceInfo deviceInfo, String ip, String code, boolean needRateLimit) { + //todo 校验邮箱 + + if (StringUtils.isBlank(code)) { + code = String.format("%d", RandomUtil.getFiveRandomNumber()); + } + + String intervalKey = RedisKey.email_send_interval.getKey(emailAddress, type.toString()); + RBucket intervalBucket = redissonClient.getBucket(intervalKey); + if (intervalBucket.isExists()) { + throw new ServiceException(BusiStatus.SMS_NOT_EXPIRED); + } + + RRateLimiter rateLimiter = null; + if (needRateLimit){ + String ipKey = RedisKey.email_send_interval.getKey(ip); + rateLimiter = redissonClient.getRateLimiter(ipKey); + if (!rateLimiter.isExists()) { + rateLimiter.trySetRate(RateType.OVERALL, 5, 1, RateIntervalUnit.DAYS); + } + + if (!rateLimiter.tryAcquire()){ + log.error("[email rateLimiter] {} {} 被限流了", ip, type); + throw new ServiceException(BusiStatus.SMS_IP_TO_OFTEN); + } + } + + + //新增短信记录 + emailRecordService.saveRecord(emailAddress, deviceInfo, ip, code, type, null, null); + //todo 响应编码校验 + + // 写入短信发送频率 + intervalBucket.set(StrUtil.EMPTY, EmailConstant.SEND_INTERVAL_SECONDS, TimeUnit.SECONDS); + + // 写入缓存 + String codeKey = RedisKey.email_code.getKey(emailAddress); + RBucket codeBucket = redissonClient.getBucket(codeKey); + codeBucket.set(code, EmailConstant.EXPIRE_SECONDS, TimeUnit.SECONDS); + + if (null != rateLimiter){ + rateLimiter.expire(1, TimeUnit.DAYS); + } + } + + public boolean verifyEmailCode(String emailAddress, String code) { + logger.info("verifyEmailCode emailAddress : {}, code : {}", emailAddress, code); + + Assert.notNull(emailAddress, "mobile is null"); + Assert.notNull(code, "code is null"); + + // 写入缓存 + String codeKey = RedisKey.email_code.getKey(emailAddress); + RBucket codeBucket = redissonClient.getBucket(codeKey); + String codeCache = codeBucket.get(); + + logger.info("verifySmsCode codeKey : {}, codeCache : {} code : {}", codeKey, codeCache, code); + if (StringUtils.equalsIgnoreCase(codeCache, code)) { + return codeBucket.delete(); + } + return false; + } + +} diff --git a/accompany-base/accompany-email/pom.xml b/accompany-base/accompany-email/pom.xml new file mode 100644 index 000000000..74ea23483 --- /dev/null +++ b/accompany-base/accompany-email/pom.xml @@ -0,0 +1,19 @@ + + + 4.0.0 + + com.accompany + accompany-base + 1.0.0 + + + accompany-email + pom + + accompany-email-sdk + accompany-email-service + + + \ No newline at end of file diff --git a/accompany-base/accompany-sms/accompany-sms-service/src/main/java/com/accompany/sms/config/AliyunSmsConfig.java b/accompany-base/accompany-sms/accompany-sms-sdk/src/main/java/com/accompany/sms/config/AliyunSmsConfig.java similarity index 100% rename from accompany-base/accompany-sms/accompany-sms-service/src/main/java/com/accompany/sms/config/AliyunSmsConfig.java rename to accompany-base/accompany-sms/accompany-sms-sdk/src/main/java/com/accompany/sms/config/AliyunSmsConfig.java diff --git a/accompany-base/accompany-sms/accompany-sms-service/src/main/java/com/accompany/sms/config/TencentSmsConfig.java b/accompany-base/accompany-sms/accompany-sms-sdk/src/main/java/com/accompany/sms/config/TencentSmsConfig.java similarity index 100% rename from accompany-base/accompany-sms/accompany-sms-service/src/main/java/com/accompany/sms/config/TencentSmsConfig.java rename to accompany-base/accompany-sms/accompany-sms-sdk/src/main/java/com/accompany/sms/config/TencentSmsConfig.java diff --git a/accompany-base/accompany-sms/accompany-sms-service/src/main/java/com/accompany/sms/strategy/SmsStrategy.java b/accompany-base/accompany-sms/accompany-sms-service/src/main/java/com/accompany/sms/strategy/SmsStrategy.java index df5ff32c9..ffce0c300 100644 --- a/accompany-base/accompany-sms/accompany-sms-service/src/main/java/com/accompany/sms/strategy/SmsStrategy.java +++ b/accompany-base/accompany-sms/accompany-sms-service/src/main/java/com/accompany/sms/strategy/SmsStrategy.java @@ -1,5 +1,8 @@ package com.accompany.sms.strategy; +import com.accompany.sms.strategy.SmsContext; +import com.accompany.sms.strategy.SmsResponse; + /** * @author: liaozetao * @date: 2023/8/14 14:59 diff --git a/accompany-base/pom.xml b/accompany-base/pom.xml index 6aa9f464e..e87a68d64 100644 --- a/accompany-base/pom.xml +++ b/accompany-base/pom.xml @@ -19,6 +19,7 @@ accompany-payment accompany-sharding accompany-sms + accompany-email \ No newline at end of file diff --git a/accompany-business/accompany-business-sdk/pom.xml b/accompany-business/accompany-business-sdk/pom.xml index 363a1f2e0..f33286d88 100644 --- a/accompany-business/accompany-business-sdk/pom.xml +++ b/accompany-business/accompany-business-sdk/pom.xml @@ -33,6 +33,11 @@ accompany-sms-sdk ${revision} + + com.accompany + accompany-email-sdk + ${revision} + com.accompany accompany-business-world-sdk diff --git a/accompany-business/accompany-business-service/pom.xml b/accompany-business/accompany-business-service/pom.xml index c5d127db8..98fa0ed2e 100644 --- a/accompany-business/accompany-business-service/pom.xml +++ b/accompany-business/accompany-business-service/pom.xml @@ -28,6 +28,11 @@ accompany-sms-service ${revision} + + com.accompany + accompany-email-service + ${revision} + com.accompany accompany-payment-service diff --git a/accompany-business/accompany-business-service/src/main/java/com/accompany/business/service/user/UsersService.java b/accompany-business/accompany-business-service/src/main/java/com/accompany/business/service/user/UsersService.java index c153a8661..156e1946b 100644 --- a/accompany-business/accompany-business-service/src/main/java/com/accompany/business/service/user/UsersService.java +++ b/accompany-business/accompany-business-service/src/main/java/com/accompany/business/service/user/UsersService.java @@ -65,7 +65,6 @@ import com.accompany.core.service.common.JedisService; import com.accompany.core.service.partition.PartitionInfoService; import com.accompany.core.service.phone.PhoneAuthApplyRecordService; import com.accompany.core.service.region.RegionInfoService; -import com.accompany.core.service.region.RegionNetworkSearchService; import com.accompany.core.service.region.RegionService; import com.accompany.core.service.user.UserCancelRecordService; import com.accompany.core.service.user.UsersBaseService; diff --git a/accompany-business/accompany-business-web/src/main/java/com/accompany/business/controller/EmailController.java b/accompany-business/accompany-business-web/src/main/java/com/accompany/business/controller/EmailController.java new file mode 100644 index 000000000..e6db25f66 --- /dev/null +++ b/accompany-business/accompany-business-web/src/main/java/com/accompany/business/controller/EmailController.java @@ -0,0 +1,90 @@ +package com.accompany.business.controller; + +import com.accompany.business.common.BaseController; +import com.accompany.common.constant.SmsTypeEnum; +import com.accompany.common.device.DeviceInfo; +import com.accompany.common.result.BusiResult; +import com.accompany.common.status.BusiStatus; +import com.accompany.common.utils.IPUtils; +import com.accompany.core.enumeration.PartitionEnum; +import com.accompany.core.service.account.AccountBlockCheckService; +import com.accompany.core.util.I18NMessageSourceUtil; +import com.accompany.email.service.EmailService; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import java.util.Arrays; +import java.util.List; + +import static com.accompany.core.enumeration.I18nAlertEnum.ACCOUNT_LOGIN_BLOCK_MSG; + +@Slf4j +@RestController +@RequestMapping("/email") +public class EmailController extends BaseController { + + @Autowired + private EmailService emailService; + @Autowired + private AccountBlockCheckService accountBlockCheckService; + + private final static List USE_PHONE_IN_PARAM_TYPES = Arrays.asList(SmsTypeEnum.REGISTER.value, SmsTypeEnum.LOGIN.value, SmsTypeEnum.SUPER_ADMIN_LOGIN.value, + SmsTypeEnum.RESET_PASSWORD_FOR_NO_LOGIN.value, SmsTypeEnum.BINDING_PHONE.value); + + @ApiOperation("发送邮箱验证码") + @PostMapping(value = "getCode") + public BusiResult getCode(String emailAddress, Integer type, HttpServletRequest request) { + emailAddress = decryptSensitiveInfo(request, emailAddress); + + String ip = IPUtils.getRealIpAddress(request); + DeviceInfo deviceInfo = getDeviceInfo(request); + Long uid = getUid(request); + log.info("sendEmailCode, emailAddress:{}, type:{}, uid:{}", emailAddress, type, uid); + + /*if(uid != null && !USE_PHONE_IN_PARAM_TYPES.contains(type.intValue())){ + log.info("需要通过uid获取用户已绑定的手机号"); + Users users = usersBaseService.getUsersByUid(uid); + String userMobile = users == null ? mobile : users.getPhone(); + String userAreaCode = users == null ? phoneAreaCode : users.getPhoneAreaCode(); + // 如果headers里面有pub_uid,查询用户的手机号发送验证码 + if (CommonUtil.checkPhoneFormat(userAreaCode,userMobile)) { + mobile = userMobile; + phoneAreaCode = userAreaCode; + } + }*/ + log.info("sendEmailCode, email:{}, type:{}, uid:{}", emailAddress, type, uid); + + //检查账号、设备号、号段是否封禁 + if (accountBlockCheckService.checkBlockedDevice(deviceInfo.getDeviceId())) { + return new BusiResult<>(BusiStatus.ACCOUNT_BLOCK_ERROR, I18NMessageSourceUtil.getMessage(ACCOUNT_LOGIN_BLOCK_MSG, new Object[]{deviceInfo.getDeviceId()}, PartitionEnum.ENGLISH.getId())); + } + if (accountBlockCheckService.checkBlockedIp(ip)) { + return new BusiResult<>(BusiStatus.ACCOUNT_BLOCK_ERROR, I18NMessageSourceUtil.getMessage(ACCOUNT_LOGIN_BLOCK_MSG, new Object[]{ip}, PartitionEnum.ENGLISH.getId())); + } + if (accountBlockCheckService.checkBlockedEmail(emailAddress)) { + return new BusiResult<>(BusiStatus.ACCOUNT_BLOCK_ERROR, I18NMessageSourceUtil.getMessage(ACCOUNT_LOGIN_BLOCK_MSG, new Object[]{emailAddress}, PartitionEnum.ENGLISH.getId())); + } + + emailService.sendEmailCode(emailAddress, type, deviceInfo, ip, null, true); + + return new BusiResult<>(BusiStatus.SMS_SEND_SUCCESS); + } + + @ApiParam("校验邮箱验证码") + @PostMapping(value = "/verify") + public BusiResult verify(String emailAddress, String code, HttpServletRequest request) { + emailAddress = decryptSensitiveInfo(request, emailAddress); + + boolean verify = emailService.verifyEmailCode(emailAddress, code); + if (!verify) { + return BusiResult.fail(BusiStatus.SMS_VERIFY_CODE_ERROR); + } + return BusiResult.success(); + } +} diff --git a/accompany-dependencies/pom.xml b/accompany-dependencies/pom.xml index 52659bfd3..ae732151f 100644 --- a/accompany-dependencies/pom.xml +++ b/accompany-dependencies/pom.xml @@ -87,6 +87,7 @@ 1.34.0 2.5.1 1.0.1 + 2.30.37 @@ -143,12 +144,6 @@ ${hippo4j-config-spring-boot-starter.version} - - org.redisson - redisson-spring-data-20 - ${redisson.version} - - mysql mysql-connector-java @@ -269,12 +264,6 @@ ${commons-math.version} - - net.sf.dozer - dozer - ${dozer.version} - - net.sourceforge.jchardet jchardet