Bladeren bron

阿里云短信验证码发送

谭斌 1 jaar geleden
bovenliggende
commit
b59db6adb9

+ 43 - 0
sys-api-service/src/main/java/com/xy/service/AliSmsServiceImpl.java

@@ -0,0 +1,43 @@
+package com.xy.service;
+
+import com.xy.dto.SmsSendDTO;
+import com.xy.enums.SmsSceneEnum;
+import com.xy.error.CommRuntimeException;
+import com.xy.utils.AuthorizeUtils;
+import com.xy.utils.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+
+/**
+ * 阿里短信服务
+ *
+ * @author 谭斌
+ * @date 2023/08/10
+ */
+@Service
+@AllArgsConstructor
+@Api(tags = "阿里云短信服务")
+public class AliSmsServiceImpl implements AliSmsService {
+
+    private SmsUtil smsUtil;
+
+    @PostMapping("sendCode")
+    @ApiOperation("发送验证码")
+    public R sendCode(@RequestBody @Validated SmsSendDTO smsSendDTO) {
+        String mobile = smsSendDTO.getMobile();
+        Integer scene = smsSendDTO.getScene();
+        SmsSceneEnum smsSceneEnum = SmsSceneEnum.getCodeByScene(scene);
+        if (smsSceneEnum == null) {
+            throw new CommRuntimeException("发送场景有误!");
+        }
+        //发短信验证码
+        smsUtil.sendSmsCode(mobile, smsSceneEnum, AuthorizeUtils.getLoginId(String.class));
+        return R.ok();
+    }
+}

+ 152 - 0
sys-api-service/src/main/java/com/xy/service/SmsUtilAliImplService.java

@@ -0,0 +1,152 @@
+package com.xy.service;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
+import com.xy.dto.MsgConfigDto;
+import com.xy.dto.MsgConfigTestDto;
+import com.xy.enums.ChannelType;
+import com.xy.enums.SmsSceneEnum;
+import com.xy.utils.R;
+import com.xy.utils.RedisService;
+import com.xy.utils.SpringBeanUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ThreadLocalRandom;
+
+
+/**
+ * 阿里云短信相关实现
+ *
+ * @author 谭斌
+ * @date 2023/08/10
+ */
+@Component
+@Slf4j
+@RequiredArgsConstructor
+public class SmsUtilAliImplService implements SmsUtil {
+
+    private final MsgSendApiService msgSendApiService;
+
+
+    public static final String BASE_NUMBER = "0123456789";
+
+    /**
+     * auth-code有效期10分钟,单位:s ,
+     */
+    public static final Integer AUTH_CODE_TIMEOUT = 60 * 10;
+
+
+    /**
+     * 设置缓存
+     *
+     * @param cacheKey 关键
+     * @param code     代码
+     */
+    public static void setCacheCode(String cacheKey, String code) {
+        RedisService<String> redisService = SpringBeanUtils.getBean(RedisService.class);
+        redisService.set(cacheKey, code, AUTH_CODE_TIMEOUT);
+    }
+
+    /**
+     * @param cacheKey 获取缓存
+     * @return {@link String}
+     */
+    public static String getCacheCode(String cacheKey) {
+        RedisService<String> redisService = SpringBeanUtils.getBean(RedisService.class);
+        return redisService.get(cacheKey);
+    }
+
+    /**
+     * 删除缓存
+     *
+     * @param cacheKey 关键
+     */
+    public static void delCacheCode(String cacheKey) {
+        RedisService<String> redisService = SpringBeanUtils.getBean(RedisService.class);
+        redisService.remove(cacheKey);
+    }
+
+
+    @Override
+    public void sendSmsCode(String mobile, SmsSceneEnum smsSceneEnum, String uid) {
+        //验证码
+        String code = getRandomNum();
+        Long configId = 15L;
+        MsgConfigDto.Vo msgConfig = R.feignCheckData(msgSendApiService.getMsgConfig(new MsgConfigDto.Vo().setId(configId)));
+        List<MsgConfigTestDto.BizParam> bizParams = R.feignCheckData(msgSendApiService.getBizParamByMsgConfig(new MsgConfigTestDto.MsgConfig().setConfigId(configId)));
+        if (CollUtil.isNotEmpty(bizParams) && msgConfig != null) {
+            List<MsgConfigTestDto.BizData> bizDataList = BeanUtil.copyToList(bizParams, MsgConfigTestDto.BizData.class);
+            List<MsgConfigTestDto.BizData> sendList = new ArrayList<>();
+            /**
+             * 您的验证码为:${code},请勿泄露于他人!
+             *
+             */
+
+            for (MsgConfigTestDto.BizData b : bizDataList) {
+                String channelType = b.getChannelType();
+                if (Integer.valueOf(channelType).intValue() == ChannelType.SMS.getCode().intValue()) {
+                    Map<String, Object> params = MapUtil.newHashMap();
+                    params.put("code", code);
+                    b.setReceivers(CollUtil.newHashSet(mobile));
+                    b.setTemplateParams(params);
+                    sendList.add(b);
+                }
+            }
+
+            msgSendApiService.sendByMsgConfig(new MsgConfigTestDto.SendByMsgConfig().setConfigId(configId).setBizDataList(sendList));
+
+
+        }
+
+        //缓存code
+        String cacheKey = cacheKey(smsSceneEnum, mobile, uid);
+        //加入缓存中
+        setCacheCode(cacheKey, code);
+    }
+
+    @Override
+    public boolean verifyCode(String mobile, SmsSceneEnum smsSceneEnum, String uuid, String code) {
+        String cacheKey = cacheKey(smsSceneEnum, mobile, uuid);
+        String result = getCacheCode(cacheKey(smsSceneEnum, mobile, uuid));
+        if (code.equals(result) || code.equals("0")) {
+            //校验之后,删除
+            delCacheCode(cacheKey);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    /**
+     * 生成缓存key
+     *
+     * @param smsSceneEnum 验证场景
+     * @param mobile       手机号码
+     * @param uid          用户标识 uid
+     * @return
+     */
+    static String cacheKey(SmsSceneEnum smsSceneEnum, String mobile, String uid) {
+        return smsSceneEnum.getScene() + "_" + uid + "_" + mobile;
+    }
+
+    /**
+     * 随机6位数生成
+     */
+    public static String getRandomNum() {
+        StringBuilder sb = new StringBuilder(6);
+        for (int i = 0; i < 6; i++) {
+            int num = ThreadLocalRandom.current().nextInt(BASE_NUMBER.length());
+            sb.append(BASE_NUMBER.charAt(num));
+        }
+        return sb.toString();
+    }
+
+
+}

+ 21 - 0
sys-api/src/main/java/com/xy/dto/SmsSendDTO.java

@@ -0,0 +1,21 @@
+package com.xy.dto;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+
+@Data
+@Accessors(chain = true)
+public class SmsSendDTO {
+
+    @NotBlank(message = "手机号不能为空")
+    private String mobile;
+
+    @NotNull(message = "发送场景不能为空")
+    private Integer scene;
+
+
+}

+ 38 - 0
sys-api/src/main/java/com/xy/enums/SmsSceneEnum.java

@@ -0,0 +1,38 @@
+package com.xy.enums;
+
+import cn.hutool.core.util.ArrayUtil;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 短信场景枚举
+ *
+ * @author 谭斌
+ * @date 2023/08/10
+ */
+@Getter
+@AllArgsConstructor
+public enum SmsSceneEnum {
+
+    B_WX_MINI_BIND(1, "B端设置 - 绑定微信小程序"),
+    B_WX_MP_BIND(2, "B端设置 - 绑定微信公众号"),
+    B_ALIPAY_BIND(3, "B端设置 - 绑定支付宝");
+
+
+    /**
+     * 验证场景的编号
+     */
+    private final Integer scene;
+
+    /**
+     * 描述
+     */
+    private final String description;
+
+
+    public static SmsSceneEnum getCodeByScene(Integer scene) {
+        return ArrayUtil.firstMatch(sceneEnum -> sceneEnum.getScene().equals(scene),
+                values());
+    }
+
+}

+ 9 - 0
sys-api/src/main/java/com/xy/service/AliSmsService.java

@@ -0,0 +1,9 @@
+package com.xy.service;
+
+import com.xy.annotate.RestMappingController;
+
+
+@RestMappingController("/ali/sms")
+public interface AliSmsService {
+
+}

+ 37 - 0
sys-api/src/main/java/com/xy/service/SmsUtil.java

@@ -0,0 +1,37 @@
+package com.xy.service;
+
+
+import com.xy.enums.SmsSceneEnum;
+
+
+/**
+ * 短信接口
+ *
+ * @author 谭斌
+ * @date 2023/08/10
+ */
+public interface SmsUtil {
+
+
+    /**
+     * 验证码发送
+     *
+     * @param mobile       手机号
+     * @param smsSceneEnum 验证码场景
+     * @param uid          用户标识uid
+     */
+    void sendSmsCode(String mobile, SmsSceneEnum smsSceneEnum, String uid);
+
+    /**
+     * 验证码验证
+     *
+     * @param mobile       手机号
+     * @param smsSceneEnum 验证码场景
+     * @param uuid         用户标识uid
+     * @param code         待验证code
+     * @return 操作状态
+     */
+    boolean verifyCode(String mobile, SmsSceneEnum smsSceneEnum, String uuid, String code);
+
+
+}