17. 尚融宝引入阿里云短信服务

一、使用RAM子用户

1、进入子用户管理页面

在这里插入图片描述

在这里插入图片描述

2、添加用户

在这里插入图片描述

3、获取子用户key

AccessKeyId, AccessKeySecret

4、设置用户权限

授权:AliyunDysmsFullAccess

在这里插入图片描述

二、开通短信服务

1、开通

在这里插入图片描述

在这里插入图片描述

2、添加签名

在这里插入图片描述

3、添加模板

在这里插入图片描述

在这里插入图片描述

4、套餐

http://free.aliyun.com

在这里插入图片描述

5、快速学习

在这里插入图片描述

三、测试短信发送

1、查找使用示例

在这里插入图片描述

2、测试短信发送

在这里插入图片描述
在这里插入图片描述

3、查看发送结果

短信服务->业务统计->发送记录查询

四、创建项目

需求

在这里插入图片描述

在这里插入图片描述

1、创建service-sms模块

2、配置 pom.xml

	<dependencies>
		<dependency>
			<groupId>com.indi</groupId>
			<artifactId>service-base</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!--lombok用来简化实体类:需要安装lombok插件-->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>

		<!--阿里云短信-->
		<dependency>
			<groupId>com.aliyun</groupId>
			<artifactId>aliyun-java-sdk-core</artifactId>
		</dependency>
	</dependencies>

3、application.yml

resources目录下创建文件

server:
  port: 8120 # 服务端口

spring:
  profiles:
    active: dev # 环境设置
  application:
    name: service-sms # 服务名

  #spring:
  redis:
    host: 192.168.2.190
    port: 6379
    database: 0
    password: 123456 #没有密码,则去掉此选项
    timeout: 3000ms #最大等待时间,超时则抛出异常,否则请求一直等待
    lettuce:
      pool:
        max-active: 20  #最大连接数,负值表示没有限制,默认8
        max-wait: -1    #最大阻塞等待时间,负值表示没限制,默认-1
        max-idle: 8     #最大空闲连接,默认8
        min-idle: 0     #最小空闲连接,默认0

#阿里云短信
aliyun:
  sms:
    region-id: cn-hangzhou
    key-id: 你的keyid
    key-secret: 你的keysecret
    template-code: 你的短信模板code
    sign-name: 你的短信模板签名

4、logback-spring.xml

复制之前sms-core模块的,只需要修改日志输出目录即可
在这里插入图片描述

5、创建SpringBoot启动类

ServiceSmsApplication.java

package com.indi.srb.sms;

@SpringBootApplication
@ComponentScan({"com.indi.srb","com.indi.common"})
public class ServiceSmsApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceSmsApplication.class, args);
    }
}

五、自定义配置

1、从配置文件读取常量

com.indi.srb.sms.util包下
创建常量读取工具类:SmsProperties.java

package com.indi.srb.sms.util;

@Data
@Component
@ConfigurationProperties(prefix = "aliyun.sms")
public class SmsProperties implements InitializingBean {
    private String regionId;
    private String keyId;
    private String keySecret;
    private String templateCode;
    private String signName;

    public static String REGION_Id;
    public static String KEY_ID;
    public static String KEY_SECRET;
    public static String TEMPLATE_CODE;
    public static String SIGN_NAME;

    //当私有成员被赋值后,此方法自动被调用,从而初始化常量
    @Override
    public void afterPropertiesSet() throws Exception {
        REGION_Id = regionId;
        KEY_ID = keyId;
        KEY_SECRET = keySecret;
        TEMPLATE_CODE = templateCode;
        SIGN_NAME = signName;
    }
}

Idea报告如下错误信息(不影响程序的编译和运行):
在这里插入图片描述

解决步骤:

  1. pom添加依赖

    		<!--  配置文件处理器  -->
    		<!--让自定义的配置在application.yaml进行自动提示-->
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-configuration-processor</artifactId>
    			<optional>true</optional>
    		</dependency>
    
  2. 启用processor在这里插入图片描述

  3. 重新编译模块

  4. 这样在yml文件中写阿里云的配置时,就有提示了

2、测试工具类

test模块下创建UtilsTests.java

package com.indi.srb.sms;
@SpringBootTest
@RunWith(SpringRunner.class)

public class UtilsTests {
    @Test
    public void testProperties(){
        System.out.println(SmsProperties.KEY_ID);
        System.out.println(SmsProperties.KEY_SECRET);
        System.out.println(SmsProperties.REGION_Id);
    }
}

六、发送短信

1、短信发送业务

SmsService.java

package com.indi.srb.sms.service;

public interface SmsService {
    void send(String mobile, String templateCode, Map<String,Object> param);
}

SmsServiceImpl.java

@Service
@Slf4j
public class SmsServiceImpl implements SmsService {
    @Override
    public void send(String mobile, String templateCode, Map<String,Object> param) {
        //创建远程连接客户端对象
        DefaultProfile profile = DefaultProfile.getProfile(
                SmsProperties.REGION_Id,
                SmsProperties.KEY_ID,
                SmsProperties.KEY_SECRET);
        IAcsClient client = new DefaultAcsClient(profile);

        //创建远程连接的请求参数
        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", SmsProperties.REGION_Id);
        request.putQueryParameter("PhoneNumbers", mobile);
        request.putQueryParameter("SignName", SmsProperties.SIGN_NAME);
        request.putQueryParameter("TemplateCode", templateCode);

        Gson gson = new Gson();
        String json = gson.toJson(param);
        request.putQueryParameter("TemplateParam", json);

        try {
            // 使用客户端对象携带请求参数向远程阿里云服务器发起远程调用,并得到响应结果
            CommonResponse response = client.getCommonResponse(request);

            // 通信失败的处理
            boolean success = response.getHttpResponse().isSuccess();
            // ALIYUN_RESPONSE_FAIL(-501, "阿里云响应失败"),
            Assert.isTrue(success, ResponseEnum.ALIYUN_RESPONSE_FAIL);

            // 获取响应结果
            String data = response.getData();
            HashMap<String, String> resultMap = gson.fromJson(data, HashMap.class);
            String code = resultMap.get("Code");
            String message = resultMap.get("Message");
            log.info("阿里云短信发送响应结果:");
            log.info("code:" + code);
            log.info("message:" + message);

            // 业务失败的处理
            Assert.notEquals("isv.BUSINESS_LIMIT_CONTROL", code, ResponseEnum.ALIYUN_SMS_LIMIT_CONTROL_ERROR);
            Assert.equals("OK", code, ResponseEnum.ALIYUN_SMS_ERROR);

        } catch (ServerException e) {
            log.error("阿里云短信发送SDK调用失败:");
            log.error("ErrorCode=" + e.getErrCode());
            log.error("ErrorMessage=" + e.getErrMsg());
            throw new BusinessException(ResponseEnum.ALIYUN_SMS_ERROR , e);
        } catch (ClientException e) {
            log.error("阿里云短信发送SDK调用失败:");
            log.error("ErrorCode=" + e.getErrCode());
            log.error("ErrorMessage=" + e.getErrMsg());
            throw new BusinessException(ResponseEnum.ALIYUN_SMS_ERROR , e);
        }
    }
}

2、引入工具类

indi-common模块中创建util包,存放工具类
RandomUtils.java:生成四位或六位的验证码

package com.indi.common.util;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

/**
 * 生成四位和六位的随机数字
 */
public class RandomUtils {

	private static final Random random = new Random();

	private static final DecimalFormat fourdf = new DecimalFormat("0000");

	private static final DecimalFormat sixdf = new DecimalFormat("000000");

	public static String getFourBitRandom() {
		return fourdf.format(random.nextInt(10000));
	}

	public static String getSixBitRandom() {
		return sixdf.format(random.nextInt(1000000));
	}

	/**
	 * 给定数组,抽取n个数据
	 * @param list
	 * @param n
	 * @return
	 */
	public static ArrayList getRandom(List list, int n) {

		Random random = new Random();

		HashMap<Object, Object> hashMap = new HashMap<Object, Object>();

		// 生成随机数字并存入HashMap
		for (int i = 0; i < list.size(); i++) {

			int number = random.nextInt(100) + 1;

			hashMap.put(number, i);
		}

		// 从HashMap导入数组
		Object[] robjs = hashMap.values().toArray();

		ArrayList r = new ArrayList();

		// 遍历数组并打印数据
		for (int i = 0; i < n; i++) {
			r.add(list.get((int) robjs[i]));
			System.out.print(list.get((int) robjs[i]) + "\t");
		}
		System.out.print("\n");
		return r;
	}
}

RegexValidateUtils.java:常用正则表达式验证,这里提供了手机号码验证

package com.indi.common.util;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 使用正则表达式进行表单验证
 */
public class RegexValidateUtils {

    static boolean flag = false;
    static String regex = "";

    public static boolean check(String str, String regex) {
        try {
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(str);
            flag = matcher.matches();
        } catch (Exception e) {
            flag = false;
        }
        return flag;
    }

    /**
     * 验证邮箱
     *
     * @param email
     * @return
     */
    public static boolean checkEmail(String email) {
        String regex = "^\\w+[-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$ ";
        return check(email, regex);
    }

    /**
     * 验证手机号码
     *
     * 移动号码段:139、138、137、136、135、134、150、151、152、157、158、159、182、183、187、188、147
     * 联通号码段:130、131、132、136、185、186、145
     * 电信号码段:133、153、180、189
     *
     * @param cellphone
     * @return
     */
    public static boolean checkCellphone(String cellphone) {
        String regex = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\d{8}$";
        return check(cellphone, regex);
    }

    /**
     * 验证固话号码
     *
     * @param telephone
     * @return
     */
    public static boolean checkTelephone(String telephone) {
        String regex = "^(0\\d{2}-\\d{8}(-\\d{1,4})?)|(0\\d{3}-\\d{7,8}(-\\d{1,4})?)$";
        return  check(telephone, regex);
    }

    /**
     * 验证传真号码
     *
     * @param fax
     * @return
     */
    public static boolean checkFax(String fax) {
        String regex = "^(0\\d{2}-\\d{8}(-\\d{1,4})?)|(0\\d{3}-\\d{7,8}(-\\d{1,4})?)$";
        return check(fax, regex);
    }

    /**
     * 验证QQ号码
     *
     * @param QQ
     * @return
     */
    public static boolean checkQQ(String QQ) {
        String regex = "^[1-9][0-9]{4,} $";
        return check(QQ, regex);
    }
}

3、创建controller

创建controller.api包,创建类ApiSmsController.java

package com.indi.srb.sms.controller.api;

@RestController
@Slf4j
@Api(tags = "短信管理")
@CrossOrigin
@RequestMapping("/api/sms")
public class ApiSmsController {
    @Resource
    private SmsService smsService;

    @Resource
    private RedisTemplate redisTemplate;

    @ApiOperation("获取验证码")
    @GetMapping("/send/{mobile}")
    public R send(
            @ApiParam(value = "手机号", required = true)
            @PathVariable String mobile) {
        // 校验手机号不能为空
        Assert.notEmpty(mobile, ResponseEnum.MOBILE_NULL_ERROR);

        // 校验手机号是否合法
        Assert.isTrue(RegexValidateUtils.checkCellphone(mobile), ResponseEnum.MOBILE_ERROR);

        String code = RandomUtils.getFourBitRandom();
        HashMap<String, Object> map = new HashMap<>();
        map.put("code", code);
        smsService.send(mobile, SmsProperties.TEMPLATE_CODE, map);

        // 将验证码存入redis
        redisTemplate.opsForValue().set("srb:sms:code:" + mobile, code, 5, TimeUnit.MINUTES);
        return R.ok().setMessage("短信发送成功");
    }
}

七、测试

http://localhost:8120/swagger-ui.html

测试正确发送
在这里插入图片描述

测试手机号码不正确
在这里插入图片描述

测试业务限流:连续发送两次短信

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值