使用Java第三方實現(xiàn)發(fā)送短信功能
一、介紹
在項目開發(fā)中,短信發(fā)送功能在很多地方都用得到,例如:通知短信、驗證碼、營銷短信、推廣短信等等,近期阿里云等云服務(wù)商的短信服務(wù)針對個人用戶不友好(需求企業(yè)資質(zhì)),現(xiàn)在給大家介紹一款的產(chǎn)品:樂訊通,針對個人用戶較為友好,可以很便捷的進行開發(fā)測試。
樂訊通官網(wǎng):http://yun.loktong.com/
二、使用步驟
1. 平臺注冊
使用手機號注冊即可。
注意:注冊成功后,默認密碼就是手機號。
可在 “系統(tǒng)管理”->"密碼管理"中進行密碼的修改 。
2. 短信簽名和短信模板
平時比較常見的驗證碼短信格式為:【碼賽客1024】:注冊驗證碼為312562,請勿泄露給他人。
前面括號中的就是短信簽名,后邊部分就是短信模板,因此可以分析出格式為:【短信簽名】:短信模板。
2.1 設(shè)置簽名
文字短信 -> 短信設(shè)置 -> 簽名管理 -> 添加新的簽名
2.2 設(shè)置模板
文字短信 -> 短信設(shè)置 -> 簽名管理 -> 添加新的模板
模板設(shè)置需要注意的是,模板中使用{}作為占位符,例如:
【短信簽名】:注冊驗證碼為{s6},請勿泄露給他人。
其中的{s6}會被替換為驗證碼,而6指的是字符最大長度,超過則無法發(fā)送。
3. 基于官方API文檔實現(xiàn)短信發(fā)送
3.1 官方demo
API文檔 -> 開發(fā)引導(dǎo) -> 代碼示例 -> Java ,代碼如下
package com.ljs;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.Console;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.MalformedParameterizedTypeException;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.lang.model.element.VariableElement;
import javax.management.monitor.MonitorSettingException;
import javax.print.attribute.standard.DateTimeAtCompleted;
import org.junit.Test;
public class MyTest {
public static void main(String[] args) throws ParseException {
//時間戳
long timestamp = System.currentTimeMillis();
System.out.println(timestamp);
//url
String url = "http://www.lokapi.cn/smsUTF8.aspx";
//簽名,在發(fā)送時使用md5加密
String beforSign = "action=sendtemplate&username=18586975869&password="+getMD5String("18586975869")+"&token=389c1a49×tamp="+timestamp;
//參數(shù)串
String postData = "action=sendtemplate&username=18586975869&password="+getMD5String("18586975869")+"&token=389c1a49&templateid=CF2D56FC¶m=18586975869|666666&rece=json×tamp="+timestamp+"&sign="+getMD5String(beforSign);
//調(diào)用其提供的發(fā)送短信方法
String result = sendPost(url,postData);
System.out.println(result);
}
//發(fā)送短信的方法
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打開和URL之間的連接
URLConnection conn = realUrl.openConnection();
// 設(shè)置通用的請求屬性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 發(fā)送POST請求必須設(shè)置如下兩行
conn.setDoOutput(true);
conn.setDoInput(true);
// 獲取URLConnection對象對應(yīng)的輸出流
out = new PrintWriter(conn.getOutputStream());
// 發(fā)送請求參數(shù)
out.print(param);
// flush輸出流的緩沖
out.flush();
// 定義BufferedReader輸入流來讀取URL的響應(yīng)
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("發(fā)送 POST 請求出現(xiàn)異常!"+e);
e.printStackTrace();
}finally{ //使用finally塊來關(guān)閉輸出流、輸入流
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
//用來計算MD5的函數(shù)
public static String getMD5String(String rawString){
String[] hexArray = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
try{
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(rawString.getBytes());
byte[] rawBit = md.digest();
String outputMD5 = " ";
for(int i = 0; i<16; i++){
outputMD5 = outputMD5+hexArray[rawBit[i]>>>4& 0x0f];
outputMD5 = outputMD5+hexArray[rawBit[i]& 0x0f];
}
return outputMD5.trim();
}catch(Exception e){
System.out.println("計算MD5值發(fā)生錯誤");
e.printStackTrace();
}
return null;
}
/**
* 生成秘鑰
*
* @param tm
* @param key
* @return
*/
public static String createSign(TreeMap<String, String> tm, String key) {
StringBuffer buf = new StringBuffer(key);
for (Map.Entry<String, String> en : tm.entrySet()) {
String name = en.getKey();
String value = en.getValue();
if (!"sign".equals(name) && !"param".equals(name) && value != null && value.length() > 0 && !"null".equals(value)) {
buf.append(name).append('=').append(value).append('&');
}
}
String _buf = buf.toString();
return _buf.substring(0, _buf.length() - 1);
}
/**
* 將文件轉(zhuǎn)成base64 字符串
* @param path文件路徑
* @return *
* @throws Exception
*/
public static String encodeBase64File(String path) throws Exception {
File file = new File(path);;
FileInputStream inputFile = new FileInputStream(file);
byte[] buffer = new byte[(int) file.length()];
inputFile.read(buffer);
inputFile.close();
//return new BASE64Encoder().encode(buffer);
return "";
}
}
3.2 文字短信-模板發(fā)送
1.請求地址,UTF8編碼請求地址:http://www.lokapi.cn/smsUTF8.aspx
2.請求協(xié)議:http
3.請求方式:采用post方式提交請求
4.請求報文:action=sendtemplate&username=zhangsan&password=E10ADC3949BA59ABBE56E057F20F883E&token=894gbhy&templateid=638fgths¶m=手機號1|參數(shù)1|參數(shù)2@手機號2|參數(shù)1|參數(shù)2&rece=json×tamp=636949832321055780&sign=96E79218965EB72C92A54
5.參數(shù)說明
| 參數(shù)名稱 | 是否必須 | 描述 | 示例 |
| action | 是 | 操作類型 | (固定值)action=sendtemplate |
| username | 是 | 賬戶名 | username=zhangsan |
| password | 是 | 賬戶密碼,密碼必須MD5加密并且取32位大寫 | password=E10ADC3949BA59ABBE56E057F20F883E |
| token | 是 | 產(chǎn)品總覽頁面對應(yīng)產(chǎn)品的Token | token=894gbhy |
| templateid | 是 | 模板管理報備的模板ID | templateid=638fgths |
| param | 是 | 發(fā)送參數(shù),可發(fā)送一個或多個手機號,建議單次提交最多5000個號碼 | 17712345678|張三|2541@13825254141|李四|2536 |
| dstime | 否 | 設(shè)置要發(fā)送短信的時間,精確到秒(yyyy-MM-dd HH:mm:ss) | 2017-01-05 16:23:23 |
| rece | 否 | 返回類型json、xml,默認(json) | rece=json |
| timestamp | 是 | 時間戳,13位時間戳,單位(毫秒) | timestamp=636949832321055780 |
| sign | 是 | 簽名校驗 | sign=96E79218965EB72C92A54 |
param參數(shù)詳細說明
發(fā)送一個手機號模板為【手機號1|參數(shù)1|參數(shù)2】
發(fā)送多個手機號模板為【手機號1|參數(shù)1|參數(shù)2@手機號2|參數(shù)3|參數(shù)4@…】
第一列必須為手機號,參數(shù)1,參數(shù)2對應(yīng)短信模板里的參數(shù)順序,英文豎線隔開, 比如短信模板為【簽名】您好,{s6},您的驗證碼是:{s6},參數(shù)1就對應(yīng)您好后邊的{s6},參數(shù)2對應(yīng)驗證碼是后邊的{s6}, 多個手機號以@隔開。
若模板內(nèi)沒有參數(shù)則只輸入手機號即可。
sign參數(shù)詳細說明
簽名由參數(shù)action,username,password,token,timestamp進行MD5加密組成
比如這些值拼接后為action=sendtemplate&username=zhangsan&password=E10ADC3949BA59ABBE56E057F20F883E&token=588aaaaa×tamp=636949832321055780,那么就MD5加密這個參數(shù)字符串得到結(jié)果后作為sign的值sign=96E79218965EB72C92A54
基于官方j(luò)ava代碼和參數(shù)說明,替換自己的值,即可實現(xiàn)發(fā)送。
6.返回結(jié)果
//成功返回
{
"returnstatus":"success",
"code":"0",
"taskID":[
{
"tel_17712345678":"15913494519502337"
}
]
}
//失敗返回
{
"returnstatus":"error",
"code":"-51",
"remark":"訪問超時!"
}
三、封裝發(fā)送短信工具類
1.添加 fastjson 的依賴,用于把返回結(jié)果轉(zhuǎn)為對象,方便處理。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
2.工具類如下
public class SendSMSUtil {
/**
* 封裝的發(fā)驗證碼的方法
* @param account 平臺賬戶
* @param password 平臺密碼
* @param token 平臺token
* @param templateid 短信模板id
* @param phone 短信接收方手機號
* @param code 驗證碼
* @return
*/
public static MsgResult sendMsgPost(String account,String password,String token,String templateid,String phone,String code){
//時間戳
long timestamp = System.currentTimeMillis();
//System.out.println(timestamp);
//url
String url = "http://www.lokapi.cn/smsUTF8.aspx";
//簽名
String beforSign = "action=sendtemplate&username="+account+"&password="+getMD5String(password)+"&token="+token+"×tamp="+timestamp;
//參數(shù)串
String postData = "action=sendtemplate&username="+account+"&password="+getMD5String(password)+"&token="+token+"&templateid="+templateid+"¶m="+phone+"|"+code+"&rece=json×tamp="+timestamp+"&sign="+getMD5String(beforSign);
//發(fā)送請求
String result = sendPost(url,postData);
//將json結(jié)果轉(zhuǎn)為對象,方便判斷
MsgResult msgResult = JSON.parseObject(result, MsgResult.class);
return msgResult;
}
//原本的發(fā)送方法
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打開和URL之間的連接
URLConnection conn = realUrl.openConnection();
// 設(shè)置通用的請求屬性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 發(fā)送POST請求必須設(shè)置如下兩行
conn.setDoOutput(true);
conn.setDoInput(true);
// 獲取URLConnection對象對應(yīng)的輸出流
out = new PrintWriter(conn.getOutputStream());
// 發(fā)送請求參數(shù)
out.print(param);
// flush輸出流的緩沖
out.flush();
// 定義BufferedReader輸入流來讀取URL的響應(yīng)
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("發(fā)送 POST 請求出現(xiàn)異常!"+e);
e.printStackTrace();
} finally{ //使用finally塊來關(guān)閉輸出流、輸入流
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
//用來計算MD5的函數(shù)
public static String getMD5String(String rawString){
String[] hexArray = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
try{
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(rawString.getBytes());
byte[] rawBit = md.digest();
String outputMD5 = " ";
for(int i = 0; i<16; i++){
outputMD5 = outputMD5+hexArray[rawBit[i]>>>4& 0x0f];
outputMD5 = outputMD5+hexArray[rawBit[i]& 0x0f];
}
return outputMD5.trim();
}catch(Exception e){
System.out.println("計算MD5值發(fā)生錯誤");
e.printStackTrace();
}
return null;
}
}
用于接收返回值的對象
public class MsgResult{
//返回描述
private String returnstatus;
//返回狀態(tài)碼
private Integer code;
//錯誤消息
private String remark;
public String getReturnstatus() {
return returnstatus;
}
public void setReturnstatus(String returnstatus) {
this.returnstatus = returnstatus;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
@Override
public String toString() {
return "MsgResult{" +
"returnstatus='" + returnstatus + '\'' +
", code=" + code +
", remark='" + remark + '\'' +
'}';
}
}
3.調(diào)用測試
public class SendSMSTest {
public static void main(String[] args) throws ParseException {
//使用工具類發(fā)送短信,返回封裝的對象
MsgResult msgResult = SendSMSUtil.sendMsgPost("平臺賬號","平臺密碼","token","短信模板id","接受方手機號","驗證碼");
//進行判斷
if("success".equals(msgResult.getReturnstatus()) && msgResult.getCode()==0){
System.out.println("發(fā)送成功");
}else{
System.out.println("發(fā)送失敗,原因是:"+msgResult.getRemark());
}
}
}
到此這篇關(guān)于使用Java第三方實現(xiàn)發(fā)送短信功能的文章就介紹到這了,更多相關(guān)Java實現(xiàn)發(fā)短信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
永中文檔在線轉(zhuǎn)換服務(wù)Swagger調(diào)用說明
這篇文章主要為大家介紹了永中文檔在線轉(zhuǎn)換服務(wù)Swagger調(diào)用說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06
運行Springboot測試類查詢數(shù)據(jù)庫數(shù)據(jù)顯示白網(wǎng)頁問題及解決方法
Spring Boot應(yīng)用未能啟動的原因是它沒有找到合適的數(shù)據(jù)庫配置具體來說,它需要一個數(shù)據(jù)源(DataSource),但未能在你的配置中找出,也沒有找到任何嵌入式數(shù)據(jù)庫(H2, HSQL 或 Derby),本文給大家分享運行Springboot測試類查詢數(shù)據(jù)庫數(shù)據(jù)顯示白網(wǎng)頁問題及解決方法,一起看看吧2023-11-11
ReentrantLock條件變量使多個線程順序執(zhí)行
這篇文章主要為大家介紹了ReentrantLock條件變量使多個線程順序執(zhí)行,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12
Spring整合SpringMVC + Mybatis基礎(chǔ)框架的配置文件詳解
這篇文章主要介紹了Spring整合SpringMVC + Mybatis基礎(chǔ)框架的配置文件,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02

