本文小编为大家详细介绍“怎么使用Java第三方实现发送短信功能”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么使用Java第三方实现发送短信功能”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
一、介绍
在项目开发中,短信发送功能在很多地方都用得到,例如:通知短信、验证码、营销短信、推广短信等等,近期阿里云等云服务商的短信服务针对个人用户不友好(需求企业资质),现在给大家介绍一款的产品:乐讯通,针对个人用户较为友好,可以很便捷的进行开发测试。
二、使用步骤
1. 平台注册
使用手机号注册即可。
注意:注册成功后,默认密码就是手机号。
可在 “系统管理”->"密码管理"中进行密码的修改 。
2. 短信签名和短信模板
平时比较常见的验证码短信格式为:
【码赛客1024】:注册验证码为312562,请勿泄露给他人。
前面括号中的就是短信签名,后边部分就是短信模板,因此可以分析出格式为:
【短信签名】:短信模板。
2.1 设置签名
文字短信 -> 短信设置 -> 签名管理 -> 添加新的签名
2.2 设置模板
文字短信 -> 短信设置 -> 签名管理 -> 添加新的模板
模板设置需要注意的是,模板中使用{}作为占位符,例如:
【短信签名】:注册验证码为{s6},请勿泄露给他人。
其中的{s6}会被替换为验证码,而6指的是字符最大长度,超过则无法发送。
3. 基于官方API文档实现短信发送
3.1 官方demo
API文档 -> 开发引导 -> 代码示例 -> 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"; //签名,在发送时使用md5加密 String beforSign = "action=sendtemplate&username=18586975869&password="+getMD5String("18586975869")+"&token=389c1a49×tamp="+timestamp; //参数串 String postData = "action=sendtemplate&username=18586975869&password="+getMD5String("18586975869")+"&token=389c1a49&templateid=CF2D56FC¶m=18586975869|666666&rece=json×tamp="+timestamp+"&sign="+getMD5String(beforSign); //调用其提供的发送短信方法 String result = sendPost(url,postData); System.out.println(result); } //发送短信的方法 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(); // 设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); // 获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(param); // flush输出流的缓冲 out.flush(); // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader( new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!"+e); e.printStackTrace(); }finally{ //使用finally块来关闭输出流、输入流 try{ if(out!=null){ out.close(); } if(in!=null){ in.close(); } } catch(IOException ex){ ex.printStackTrace(); } } return result; } //用来计算MD5的函数 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值发生错误"); 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); } /** * 将文件转成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 文字短信-模板发送
1.请求地址,UTF8编码请求地址:
http://www.lokapi.cn/smsUTF8.aspx
2.请求协议:
http
3.请求方式:采用
post方式提交请求
4.请求报文:
action=sendtemplate&username=zhangsan&password=E10ADC3949BA59ABBE56E057F20F883E&token=894gbhy&templateid=638fgths¶m=手机号1|参数1|参数2@手机号2|参数1|参数2&rece=json×tamp=636949832321055780&sign=96E79218965EB72C92A54
5.参数说明
参数名称 | 是否必须 | 描述 | 示例 |
action | 是 | 操作类型 | (固定值)action=sendtemplate |
username | 是 | 账户名 | username=zhangsan |
password | 是 | 账户密码,密码必须MD5加密并且取32位大写 | password=E10ADC3949BA59ABBE56E057F20F883E |
token | 是 | 产品总览页面对应产品的Token | token=894gbhy |
templateid | 是 | 模板管理报备的模板ID | templateid=638fgths |
param | 是 | 发送参数,可发送一个或多个手机号,建议单次提交最多5000个号码 | 17712345678|张三|2541@13825254141|李四|2536 |
dstime | 否 | 设置要发送短信的时间,精确到秒(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参数详细说明
发送一个手机号模板为【手机号1|参数1|参数2】
发送多个手机号模板为【手机号1|参数1|参数2@手机号2|参数3|参数4@…】
第一列必须为手机号,参数1,参数2对应短信模板里的参数顺序,英文竖线隔开, 比如短信模板为【签名】您好,{s6},您的验证码是:{s6},参数1就对应您好后边的{s6},参数2对应验证码是后边的{s6}, 多个手机号以@隔开。
若模板内没有参数则只输入手机号即可。
sign参数详细说明
签名由参数action,username,password,token,timestamp进行MD5加密组成
比如这些值拼接后为action=sendtemplate&username=zhangsan&password=E10ADC3949BA59ABBE56E057F20F883E&token=588aaaaa×tamp=636949832321055780,那么就MD5加密这个参数字符串得到结果后作为sign的值sign=96E79218965EB72C92A54
基于官方java代码和参数说明,替换自己的值,即可实现发送。
6.返回结果
//成功返回 { "returnstatus":"success", "code":"0", "taskID":[ { "tel_17712345678":"15913494519502337" } ] } //失败返回 { "returnstatus":"error", "code":"-51", "remark":"访问超时!" }
三、封装发送短信工具类
1.添加 fastjson 的依赖,用于把返回结果转为对象,方便处理。
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency>
2.工具类如下
public class SendSMSUtil { /** * 封装的发验证码的方法 * @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; //参数串 String postData = "action=sendtemplate&username="+account+"&password="+getMD5String(password)+"&token="+token+"&templateid="+templateid+"¶m="+phone+"|"+code+"&rece=json×tamp="+timestamp+"&sign="+getMD5String(beforSign); //发送请求 String result = sendPost(url,postData); //将json结果转为对象,方便判断 MsgResult msgResult = JSON.parseObject(result, MsgResult.class); return msgResult; } //原本的发送方法 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(); // 设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); // 获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(param); // flush输出流的缓冲 out.flush(); // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!"+e); e.printStackTrace(); } finally{ //使用finally块来关闭输出流、输入流 try{ if(out!=null){ out.close(); } if(in!=null){ in.close(); } } catch(IOException ex){ ex.printStackTrace(); } } return result; } //用来计算MD5的函数 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值发生错误"); e.printStackTrace(); } return null; } }
用于接收返回值的对象
public class MsgResult{ //返回描述 private String returnstatus; //返回状态码 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.调用测试
public class SendSMSTest { public static void main(String[] args) throws ParseException { //使用工具类发送短信,返回封装的对象 MsgResult msgResult = SendSMSUtil.sendMsgPost("平台账号","平台密码","token","短信模板id","接受方手机号","验证码"); //进行判断 if("success".equals(msgResult.getReturnstatus()) && msgResult.getCode()==0){ System.out.println("发送成功"); }else{ System.out.println("发送失败,原因是:"+msgResult.getRemark()); } } }