1. 程式人生 > >網易雲傳送簡訊驗證碼java實現

網易雲傳送簡訊驗證碼java實現

首先,登陸網易雲信註冊賬號然後獲取自己的App Key與App Secret,這裡就不多說了,可以自行百度。

在服務端API中我們可以很容易的找到這段程式碼,這是用來加密用的(關於如何加密也可以找到)

import java.security.MessageDigest;

public class CheckSumBuilder {
   // 計算並獲取CheckSum
   public static String getCheckSum(String appSecret, String nonce, String curTime) {
       return encode("sha1", appSecret + nonce + curTime);
   }
   
   // 計算並獲取md5值
   public static String getMD5(String requestBody) {
       return encode(“md5”, requestBody);
   }

   private static String encode(String algorithm, String value) {
       if (value == null) {
           return null;
       }
       try {
           MessageDigest messageDigest
                   = MessageDigest.getInstance(algorithm);
           messageDigest.update(value.getBytes());
           return getFormattedText(messageDigest.digest());
       } catch (Exception e) {
           throw new RuntimeException(e);
       }
   }
   private static String getFormattedText(byte[] bytes) {
       int len = bytes.length;
       StringBuilder buf = new StringBuilder(len * 2);
       for (int j = 0; j < len; j++) {
           buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
           buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
       }
       return buf.toString();
   }
   private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
           '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
}

接著在下面我們又可以找到這段模板程式碼,我們先看他的模板,具體資訊可以參考手冊然後瞭解它們的意義

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class Test {
   public static void main(String[] args) throws Exception{
       DefaultHttpClient httpClient = new DefaultHttpClient();
       String url = "https://api.netease.im/nimserver/user/create.action";
       HttpPost httpPost = new HttpPost(url);

       String appKey = "94kid09c9ig9k1loimjg012345123456";
       String appSecret = "123456789012";
       String nonce =  "12345";
       String curTime = String.valueOf((new Date()).getTime() / 1000L);
       String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce ,curTime);//參考 計算CheckSum的java程式碼

       // 設定請求的header
       httpPost.addHeader("AppKey", appKey);
       httpPost.addHeader("Nonce", nonce);
       httpPost.addHeader("CurTime", curTime);
       httpPost.addHeader("CheckSum", checkSum);
       httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");

       // 設定請求的引數
       List<NameValuePair> nvps = new ArrayList<NameValuePair>();
       nvps.add(new BasicNameValuePair("accid", "helloworld"));
       httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));

       // 執行請求
       HttpResponse response = httpClient.execute(httpPost);

       // 列印執行結果
       System.out.println(EntityUtils.toString(response.getEntity(), "utf-8"));
   }
}

 

然後咱們把上面的程式碼稍作修改變成如下的樣子

package tool;

import com.alibaba.fastjson.JSON;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 簡訊相關的工具類
 * 
 * @author 李嵐祺
 */
public class SMSUtils {

    private static final String NONCE = "123456";
	private static final String APP_SECRET = "你自己登陸所獲取的";
    private static final String APP_KEY = "你自己登陸所獲取的";
    
    /**
     * 驗證碼類簡訊,注意:該簡訊中驗證碼不能自己生成,由網易雲幫我們生成
     * 
     * @param mobile 手機號碼
     * @param templateId 驗證碼模板ID
     * @return 是否傳送成功
     */
    public static final boolean sendCode(String mobile, String templateId) throws IOException {
        HttpPost httpPost = new HttpPost("https://api.netease.im/sms/sendcode.action");

        String currentTime = String.valueOf(new Date().getTime()/1000L);
        String checkSum = CheckSumBuilder.getCheckSum(APP_SECRET,NONCE,currentTime);

        //set header
        httpPost.setHeader("AppKey",APP_KEY);
        httpPost.setHeader("CurTime",currentTime);
        httpPost.setHeader("Nonce",NONCE);
        httpPost.setHeader("CheckSum",checkSum);
        httpPost.setHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");

        //set data
        List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();
        nameValuePairList.add(new BasicNameValuePair("mobile",mobile));
        nameValuePairList.add(new BasicNameValuePair("templateid", templateId));
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairList,"utf-8"));

        //start request
        CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
        HttpResponse httpResponse = closeableHttpClient.execute(httpPost);
        String responseResult = EntityUtils.toString(httpResponse.getEntity(),"utf-8");
        System.out.println("responseResult:"+responseResult);

        String stateCode = JSON.parseObject(responseResult).getString("code");
        if(stateCode.equals("200")){
            return true;
        }
        return false;
    }

    /**
     * 判斷使用者輸入驗證碼與網易雲生成的驗證碼是否一致
     * 
     * @param mobile 電話號碼
     * @param code 傳送到mobile上的簡訊
     */
    public static final boolean verifyCode(String mobile, String code) throws IOException {
        HttpPost httpPost = new HttpPost("https://api.netease.im/sms/verifycode.action");

        String currentTime = String.valueOf(new Date().getTime()/1000L);
        String checkSum = CheckSumBuilder.getCheckSum(APP_SECRET,NONCE,currentTime);

        //set header
        httpPost.setHeader("AppKey",APP_KEY);
        httpPost.setHeader("CurTime",currentTime);
        httpPost.setHeader("Nonce",NONCE);
        httpPost.setHeader("CheckSum",checkSum);
        httpPost.setHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");

        //set data
        List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();
        nameValuePairList.add(new BasicNameValuePair("code",code));
        nameValuePairList.add(new BasicNameValuePair("mobile",mobile));
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairList,"utf-8"));

        //start request
        CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
        HttpResponse httpResponse = closeableHttpClient.execute(httpPost);
        String responseResult = EntityUtils.toString(httpResponse.getEntity(),"utf-8");
        System.out.println("responseResult:"+responseResult);

        String stateCode = JSON.parseObject(responseResult).getString("code");
        if(stateCode.equals("200")){
            return true;
        }
        return false;
    }
}

接下來就是測試了,我們來一個簡單的程式碼來試一試

import java.io.IOException;
import java.util.Scanner;

import tool.SMSUtils;

public class Test1 {
	
	private static String mobile = "你需要傳送簡訊的手機號";

	public static void main(String[] args) {
		try {
			SMSUtils.sendCode(mobile, "模板號(在裡面有你自己設定的傳送格式)");
		} catch (IOException e) {
			e.printStackTrace();
		}
		Scanner scanner = new Scanner(System.in);
		System.out.println("請輸入你收到的驗證碼");
		String code = scanner.nextLine();
		try {
			if(SMSUtils.verifyCode(mobile, code)) {
				System.out.println("校驗成功");
			}else {
				System.out.println("校驗失敗");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 一番操作下來之後就大功告成了,下面我們結合web來一起試一下(運用了一點點非同步),有關於這非同步,不知道的可以稍微去看看,不會用太多時間的

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title></title>
		<script type="text/javascript" src="./js/jquery-3.3.1.js"></script>
		<script>
			function sendcode(){
				var ajaxObject={
					url:"./SendcodeServlet",
					type:"GET",
					data:{
						mobile:document.getElementById("mobile").value,
					},
					dataType:"text",
					success:function(data){						
					}
				}
				$.ajax(ajaxObject);
			}
			function checkcode(){
				var ajaxObject={
					url:"./CheckcodeServlet",
					type:"GET",
					data:{mobile:document.getElementById("mobile").value,
						  code:document.getElementById("code").value
						 },
					dataType:"text",
					success:function(data){						
					}
				}
				$.ajax(ajaxObject);
			}

		</script>
	</head>
	<body>
		<input name="mobile" id="mobile" placeholder="請輸入手機號" value=""/><br />
		<input name="code" id="code" placeholder="請輸入驗證碼" value=""/><br />
		<button  onclick="sendcode()">傳送驗證碼</button>
		<button  onclick="checkcode()">提交</button>
	</body>
</html>

 接下來是倆個Servlet

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import tool.SMSUtils;

public class SendcodeServlet extends HttpServlet {
	
	private static final long serialVersionUID = 1L;
	private static String templateId = "4003516";
   
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String mobile = request.getParameter("mobile");
		System.out.println(mobile);
		SMSUtils.sendCode(mobile, templateId);
	}
}


import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import tool.SMSUtils;

public class CheckcodeServlet extends HttpServlet {
	
	private static final long serialVersionUID = 1L;
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String code = request.getParameter("code");//使用者輸入的驗證碼
		String mobile = request.getParameter("mobile");
		System.out.println(code);
		if(SMSUtils.verifyCode(mobile,code)) {
			System.out.println("成功");
			//驗證成功跳轉到成功介面
			request.getRequestDispatcher("success.jsp").forward(request, response);
		}else {
			System.out.println("失敗");
		}
	}

}

 不過在這裡我有一個疑問就是最後驗證出來是成功,也列印了出來,但是那個跳轉介面不知道為什麼沒有出現,然而到這時候我的簡訊已經全部發送完了,沒有剩餘的存貨了,有點尷尬。。。。。。先留個坑,或許之後寫類似的專案的時候我就知道了。

我覺得實現這種功能比較重要的一點就是學會去看開發者API,裡面有各種介紹,還有好多東西我也沒怎麼看,但單單看這倆種就能實現驗證碼的傳送與校驗了。