天天看點

阿裡雲接口實作發送短信驗證碼1. 阿裡雲背景配置短信相關2 java–簡單實作短信驗證碼發送3 修改短信接口4 注意點

java 阿裡雲接口實作發送短信驗證碼

  • 1. 阿裡雲背景配置短信相關
    • 1.1 開通短信服務
    • 1.2 添加模闆簽名
    • 1.3 建立秘鑰
    • 1.4 短信需要背景授權--注意點
  • 2 java--簡單實作短信驗證碼發送
    • 2.1 引入pom依賴
    • 2.2 application.yml配置阿裡AK
    • 2.3 編寫阿裡配置檔案實體類
    • 2.4 編寫阿裡工具類
    • 2.5 編寫短信緩存
    • 2.6 編寫發送短信随機碼--6位數
    • 2.7 發送短信接口
    • 2.8 校驗驗證碼有沒有過期
    • 2.9 判斷手機号是否為空,手機格式是否有誤
    • 2.10 驗證成功後,移除緩存中的手機号驗證碼
  • 3 修改短信接口
    • 3.1 添加短信類型
    • 3.2 擷取配置檔案中短信時間跟最大次數
    • 3.3 對特别類型下進行校驗
    • 3.4 動态設定失效時間
    • 3.5 規定時間内沒有失效的校驗
    • 3.6建立表,儲存短信日志,
    • 3.8 結果圖
  • 4 注意點
    • 4.1 模闆簽名正确性
    • 4.2 授權問題
    • 4.3 盡量把次數,失效時間,AK寫到配置檔案,友善修改
    • 4.4 謝謝點贊 ~^o^~

前言–很久沒更新過東西了,突然想起來短信,回顧了一下之前的小項目,把阿裡短信的内容簡要講述一下.

1. 阿裡雲背景配置短信相關

1.1 開通短信服務

打開官網,直接搜尋短信服務,點選短信控制台進入開通短信服務。

阿裡雲接口實作發送短信驗證碼1. 阿裡雲背景配置短信相關2 java–簡單實作短信驗證碼發送3 修改短信接口4 注意點

阿裡短信服務:https://www.aliyun.com/product/sms

阿裡雲接口實作發送短信驗證碼1. 阿裡雲背景配置短信相關2 java–簡單實作短信驗證碼發送3 修改短信接口4 注意點

1.2 添加模闆簽名

開通之後,配置模闆及簽名,可根據自己需求配置,稽核時間官方給得:

一般模闆預計2小時内稽核完成,稽核通過後可使用。工作時間:9:00-23:00 (法定節日順延),建議您盡量在18:00前送出申請。

1.3 建立秘鑰

AccessKey ID:***************

AccessKey Secret:**********

(建議儲存好,很關鍵得一個AK,具有該賬戶完全的權限)

1.4 短信需要背景授權–注意點

(之前遇到得一個問題)沒授權報錯,發送失敗

2 java–簡單實作短信驗證碼發送

2.1 引入pom依賴

阿裡短信服務文檔、sdk下載下傳https://help.aliyun.com/product/44282.html如果不是maven項目直接下載下傳兩個jar導入。

以下是maven

<!-- 阿裡雲短信 -->
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
    <version>1.1.0</version>
</dependency>
           

2.2 application.yml配置阿裡AK

ali:
  #阿裡AK 換成自己的
  accessKeyId: ************************
  accessKeySecret: *******************
  #短信每天發送最大次數
  sendMaxTime: 10
  #短信失效時間 例如2分鐘= 60*1000*2 =120000
  codeFailureTime: 120000
           

2.3 編寫阿裡配置檔案實體類

package com.jzyb.common.utils.wx;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "ali")
public class AliConfig {

	/** accessKeyId */
	private static String accessKeyId;

	/** accessKeySecret */
	private static String accessKeySecret;
	
	/** 短信每天發送最大次數 */
	private static Integer sendMaxTime;
	
	/** 短信失效時間 */
	private static Long codeFailureTime;
	
	public static Integer getSendMaxTime() {
		return sendMaxTime;
	}

	public void setSendMaxTime(Integer sendMaxTime) {
		AliConfig.sendMaxTime = sendMaxTime;
	}

	public static Long getCodeFailureTime() {
		return codeFailureTime;
	}

	public void setCodeFailureTime(Long codeFailureTime) {
		AliConfig.codeFailureTime = codeFailureTime;
	}

	public static String getAccessKeyId() {
		return accessKeyId;
	}

	public void setAccessKeyId(String accessKeyId) {
		AliConfig.accessKeyId = accessKeyId;
	}

	public static String getAccessKeySecret() {
		return accessKeySecret;
	}

	public void setAccessKeySecret(String accessKeySecret) {
		AliConfig.accessKeySecret = accessKeySecret;
	}

}
           

2.4 編寫阿裡工具類

package com.jzyb.common.utils.wx;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;

public class AliyunSmsUtil {
   // 産品名稱:雲通信短信API産品,開發者無需替換
   static final String product = "Dysmsapi";
   // 産品域名,開發者無需替換
   static final String domain = "dysmsapi.aliyuncs.com";

   static final String accessKeyId = AliConfig.getAccessKeyId();
   static final String accessKeySecret = AliConfig.getAccessKeySecret();

   public static SendSmsResponse sendCode(String mobile, String code) throws ClientException {

      // 可自助調整逾時時間
      System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
      System.setProperty("sun.net.client.defaultReadTimeout", "10000");

      // 初始化acsClient,暫不支援region化
      IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
      DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
      IAcsClient acsClient = new DefaultAcsClient(profile);

      // 組裝請求對象-具體描述見控制台-文檔部分内容
      SendSmsRequest request = new SendSmsRequest();
      // 必填:待發送手機号
      request.setPhoneNumbers(mobile);
      // 必填:短信簽名-可在短信控制台中找到
      // request.setSignName("蘭考縣人力資源和社會保障");
      request.setSignName("鞏義人社");
      // 必填:短信模闆-可在短信控制台中找到
      request.setTemplateCode("SMS_154500049");
      // 可選:模闆中的變量替換JSON串,如模闆内容為"親愛的${name},您的驗證碼為${code}"時,此處的值為
      request.setTemplateParam("{\"code\":\"" + code + "\"}");

      // 選填-上行短信擴充碼(無特殊需求使用者請忽略此字段)
      // request.setSmsUpExtendCode("90997");

      // 可選:outId為提供給業務方擴充字段,最終在短信回執消息中将此值帶回給調用者
      request.setOutId("yourOutId");

      // hint 此處可能會抛出異常,注意catch
      SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);

      return sendSmsResponse;
   }

   public static SendSmsResponse sendCode(String signName, String templateCode, String mobile, String code)
         throws ClientException {

      // 可自助調整逾時時間
      System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
      System.setProperty("sun.net.client.defaultReadTimeout", "10000");

      // 初始化acsClient,暫不支援region化
      IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
      DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
      IAcsClient acsClient = new DefaultAcsClient(profile);

      // 組裝請求對象-具體描述見控制台-文檔部分内容
      SendSmsRequest request = new SendSmsRequest();
      // 必填:待發送手機号
      request.setPhoneNumbers(mobile);
      // 必填:短信簽名-可在短信控制台中找到
      request.setSignName(signName);
      // 必填:短信模闆-可在短信控制台中找到
      request.setTemplateCode(templateCode);
      // 可選:模闆中的變量替換JSON串,如模闆内容為"親愛的${name},您的驗證碼為${code}"時,此處的值為
      request.setTemplateParam("{\"code\":\"" + code + "\"}");

      // 選填-上行短信擴充碼(無特殊需求使用者請忽略此字段)
      // request.setSmsUpExtendCode("90997");

      // 可選:outId為提供給業務方擴充字段,最終在短信回執消息中将此值帶回給調用者
      request.setOutId("yourOutId");

      // hint 此處可能會抛出異常,注意catch
      SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);

      return sendSmsResponse;
   }

   public static int getCode() {
      return (int) ((Math.random() * 9 + 1) * 100000);
   }

   public static void main(String[] args) {
      try {
         sendCode("模闆名", "SMS_*********", "手機号", getCode() + "");
      } catch (ClientException e) {
         e.printStackTrace();
      }
   }
}
           

2.5 編寫短信緩存

package com.jzyb.common.utils.wx;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;

public class Cache {
   // 鍵值對集合
   private final static Map<String, Entity> map = new HashMap<>();
   // 定時器線程池,用于清除過期緩存
   private final static ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

   /**
    * 添加緩存
    *
    * @param key
    *            鍵
    * @param data
    *            值
    */
   public synchronized static void put(String key, Object data) {
      Cache.put(key, data, 0);
   }

   /**
    * 添加緩存
    *
    * @param key
    *            鍵
    * @param data
    *            值
    * @param expire
    *            過期時間,機關:毫秒, 0表示無限長
    */
   public synchronized static void put(final String key, Object data, long expire) {
      // 清除原鍵值對
      Cache.remove(key);
      // 設定過期時間
      if (expire > 0) {
         Future future = executor.schedule(new Runnable() {
            @Override
            public void run() {
               // 過期後清除該鍵值對
               synchronized (Cache.class) {
                  map.remove(key);
               }
            }
         }, expire, TimeUnit.MILLISECONDS);
         map.put(key, new Entity(data, future));
      } else {
         // 不設定過期時間
         map.put(key, new Entity(data, null));
      }
   }

   /**
    * 讀取緩存
    *
    * @param key
    *            鍵
    * @return
    */
   public synchronized static Object get(String key) {
      Entity entity = map.get(key);
      return entity == null ? null : entity.getValue();
   }

   /**
    * 讀取緩存
    *
    * @param key
    *            鍵 * @param clazz 值類型
    * @return
    */
   public synchronized static <T> T get(String key, Class<T> clazz) {
      return clazz.cast(Cache.get(key));
   }

   /**
    * 清除緩存
    *
    * @param key
    * @return
    */
   public synchronized static Object remove(String key) {
      // 清除原緩存資料
      Entity entity = map.remove(key);
      if (entity == null)
         return null;
      // 清除原鍵值對定時器
      Future future = entity.getFuture();
      if (future != null)
         future.cancel(true);
      return entity.getValue();
   }

   /**
    * 查詢目前緩存的鍵值對數量
    *
    * @return
    */
   public synchronized static int size() {
      return map.size();
   }

   /**
    * 緩存實體類
    */
   private static class Entity {
      // 鍵值對的value
      private Object value;
      // 定時器Future
      private Future future;

      public Entity(Object value, Future future) {
         this.value = value;
         this.future = future;
      }

      /**
       * 擷取值
       *
       * @return
       */
      public Object getValue() {
         return value;
      }

      /**
       * 擷取Future對象
       *
       * @return
       */
      public Future getFuture() {
         return future;
      }
   }
}
           

2.6 編寫發送短信随機碼–6位數

public static int getCode(){
    return (int)((Math.random()*9+1)*100000);
}
           

2.7 發送短信接口

@ApiOperation(value = "發送短信驗證碼", notes = "通過手機号發送短信,參數:手機号")
@ApiImplicitParams({
        @ApiImplicitParam(name = "mobile", value = "15858585858", required = true, paramType = "form", dataType = "String"), })
@GetMapping(value = "sendCode", produces = { "application/json;charset=UTF-8" })
public AjaxResult sendCode(String mobile) {
    try {
        String code = getCode()+"";
        SendSmsResponse sr=AliyunSmsUtil.sendCode("模闆名", "模闆id",mobile, code);

        if("OK".equals(sr.getCode())) {
            Cache.put(mobile.trim(), code, 120000);
            String code11 = (String) Cache.get(mobile);

            return AjaxResult.success("發送成功");
        }
    } catch (ClientException e) {
        e.printStackTrace();
    }
    return AjaxResult.error("操作失敗");
}
           

2.8 校驗驗證碼有沒有過期

String oldCode = (String) Cache.get(mobile);

	if(StringUtils.isNotEmpty(oldCode)) {

    return AjaxResult.warn("之前驗證碼還沒失效");

}
           

2.9 判斷手機号是否為空,手機格式是否有誤

if(!isPhone(mobile)) {

    	return AjaxResult.warn("手機号格式有誤");

    }

   public static boolean isPhone(String phone) {

        String regex = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$";

        if (phone.length() != 11) {

            //MToast.showToast("手機号應為11位數");

            return false;

        } else {

            Pattern p = Pattern.compile(regex);

            Matcher m = p.matcher(phone);

            boolean isMatch = m.matches();

            //LogUtil.e(isMatch);

            if (!isMatch) {

               // MToast.showToast("請填入正确的手機号");

            }

            return isMatch;

        }

    }
           

2.10 驗證成功後,移除緩存中的手機号驗證碼

如果沒啥意外,即可發送成功!

{
  "msg": "發送成功",
  "code": 0
}
           

3 修改短信接口

3.1 添加短信類型

@ApiOperation(value = "發送短信驗證碼", notes = "通過手機号發送短信,參數:手機号,type類别type 1.注冊 2.修改密碼 3.修改手機号 4 修改個人資訊 5 忘記密碼")
	@ApiImplicitParams({
	@ApiImplicitParam(name = "mobile", value = "15858585858", required = true, paramType = "form", dataType = "String"), 
	@ApiImplicitParam(name = "type", value = "2", required = true, paramType = "form", dataType = "String"),})
	@GetMapping(value = "sendCode")
	public AjaxResult sendCode(String mobile,String type) {
    	if(StringUtils.isNotBlank(mobile)&&StringUtils.isNotBlank(type)){
    	//類别不為空的情況
    	}else{
    	//傳回參數為空
    	}
           

3.2 擷取配置檔案中短信時間跟最大次數

if(webSmsLogService.countByMobile(mobile)>AliConfig.getSendMaxTime()) {
    return AjaxResult.warn("當天接收驗證碼超限制");
 }
           

3.3 對特别類型下進行校驗

/* 
* 1.注冊:拿注冊舉例,如果使用者表已經有了改使用者,就沒有必要給這個人發送短信,因為已經注冊過
* 2.忘記密碼:如果使用者表根本就沒有這個手機号,就沒有必要發忘記密碼的短信--可以根據自己短信種類做判斷。規避短信濫用
*/
if("1".equals(type)) {
    	try {
    		//判斷該手機号是否已經存在--存在表示使用者已經注冊過,不存在的情況才能發注冊的驗證碼
    		if(webUserService.checkMobileSole(mobile)) {
    			return AjaxResult.warn("手機号已經存在");
    		}
    		String oldCode = (String) Cache.get(mobile);
    		if(StringUtils.isNotEmpty(oldCode)) {
    			return AjaxResult.warn("之前驗證碼還沒失效");
    		}
    		String code = getCode()+"";
    		SendSmsResponse sr=AliyunSmsUtil.sendCode("模闆名", "模闆id",mobile, code);

    		if("OK".equals(sr.getCode())) {
    			if("OK".equals(sr.getCode())) {
				//發送成功将手機号 驗證碼 失效時間儲存到Cache中
				Cache.put(mobile.trim(), code, AliConfig.getCodeFailureTime());
		 		
		 		return AjaxResult.success("發送成功");
			}
		} catch (ClientException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return AjaxResult.error("調用阿裡短信驗證碼失敗");
		}
 }
           

3.4 動态設定失效時間

3.5 規定時間内沒有失效的校驗

String oldCode = (String) Cache.get(mobile);
  	if(StringUtils.isNotEmpty(oldCode)) {
  		return AjaxResult.warn("之前驗證碼還沒失效");
	}
           

3.6建立表,儲存短信日志,

CREATE TABLE `sys_sms_log` (
	  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
	  `phone` varchar(11) DEFAULT NULL COMMENT '手機号',
	  `send_time` datetime DEFAULT NULL COMMENT '發送時間',
	  `send_status` char(1) DEFAULT NULL COMMENT '發送狀态:0失敗;1成功',
	  `content` varchar(100) DEFAULT NULL COMMENT '發送内容',
	  `send_type` char(1) DEFAULT NULL COMMENT '調用方式:1.注冊 2.修改密碼 3.修改手機号 4 修改個人資訊 5 忘記密碼.',
	  `result_code` varchar(50) DEFAULT NULL COMMENT '短信營運商的傳回碼',
	  `send_bizId` varchar(50) DEFAULT NULL COMMENT '短信發送回執ID',
	  `send_ip` varchar(20) DEFAULT NULL COMMENT '發送短信的IP位址',
	  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='短信發送日志'
           

每次發送成功後将資訊儲存短信日志表

SendSmsResponse sr=AliyunSmsUtil.sendCode("模闆名", "模闆id",mobile, code);
if("OK".equals(sr.getCode())) {
		//發送成功将手機号 驗證碼 失效時間儲存到Cache中
		Cache.put(mobile.trim(), code, AliConfig.getCodeFailureTime());
 		String code11 = (String) Cache.get(mobile);
 		WebSmsLog smslog = new WebSmsLog();
  		smslog.setContent("");
  		smslog.setPhone(mobile);
  		smslog.setResultCode("OK");
  		smslog.setSendBizid(sr.getRequestId());
  		//smslog.setSendIp(sendIp);
  		smslog.setSendStatus(1);
  		smslog.setSendTime(DateUtils.getNowDate());
  		smslog.setSendType(type);
 		sysSmsLogService.insertSysSmsLog(smslog);
 			
 		return AjaxResult.success("發送成功");
}
		    		
           

3.8 結果圖

阿裡雲接口實作發送短信驗證碼1. 阿裡雲背景配置短信相關2 java–簡單實作短信驗證碼發送3 修改短信接口4 注意點

發送結果

阿裡雲接口實作發送短信驗證碼1. 阿裡雲背景配置短信相關2 java–簡單實作短信驗證碼發送3 修改短信接口4 注意點

4 注意點

4.1 模闆簽名正确性

AK --模闆名--模闆id這些都是對應的,項目多了有時候會把另外一個項目的AK拿到這個項目用,但是模闆id卻是這個項目的,盡量多審查幾遍,保證模闆設定要與控制台的短信模闆相對應
           

4.2 授權問題

(遇到過一次)需要阿裡背景點一下

4.3 盡量把次數,失效時間,AK寫到配置檔案,友善修改

4.4 謝謝點贊 ^o^

本人小白,以上是自己的一知半解,有任何問題請留言評論,及時改正,及時回複,互相學習互相進步。手打2小時,也希望對新手有幫助,看的開心話點贊關注。原創–轉載請備明出處–叩謝!