在项目开发中,基本上离不开短信使用。如:验证码,语音验证码,订单通知,物流通知,会员通知,交易通知,变更通知等等。笔者也使用过很多平台,个人感觉摩杜云还是不错的。该平台除了支持全球280多个地区发送外,还支持区块链,交易所,金融等行业发送。此处就不在赘述了。
1.当然是到摩杜云注册个账号。
2.登录后台右上角点击accesskey进去创建accesskey、secretkey。
3.准备json_jdk1.7.jar(当然可以下载最新版的,情况根据自己需要。)
4.SmsSDKDemo.java
package com.moduyun.sdk.sms;
import com.moduyun.sdk.sms.yun.SmsSingleSender;
import com.moduyun.sdk.sms.yun.SmsSingleSenderResult;
public class SmsSDKDemo {
public static void main(String[] args) {
try {
//请根据实际 accesskey 和 secretkey 进行开发,以下只作为演示 sdk 使用
String accesskey = "xxx";
String secretkey ="xxxxx";
//手机号码
String phoneNumber = "136252412xx";
//初始化单发
SmsSingleSender singleSender = new SmsSingleSender(accesskey, secretkey);
SmsSingleSenderResult singleSenderResult;
String msg = "【摩杜云】尊敬的用户:您的验证码:123456,工作人员不会索取,请勿泄漏。";
//普通单发,注意前面必须为【】符号包含,置于头或者尾部。
singleSenderResult = singleSender.send(0, "86", phoneNumber, msg, "", "");
System.out.println(singleSenderResult);
} catch (Exception e) {
e.printStackTrace();
}
}
}
5.SmsSenderUtil.java
package com.moduyun.sdk.sms.yun;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Random;
import org.json.JSONArray;
import org.json.JSONObject;
class SmsSenderUtil {
protected Random random = new Random();
public String stringMD5(String input) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
byte[] inputByteArray = input.getBytes();
messageDigest.update(inputByteArray);
byte[] resultByteArray = messageDigest.digest();
return byteArrayToHex(resultByteArray);
}
protected String strToHash(String str) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte[] inputByteArray = str.getBytes();
messageDigest.update(inputByteArray);
byte[] resultByteArray = messageDigest.digest();
return byteArrayToHex(resultByteArray);
}
public String byteArrayToHex(byte[] byteArray) {
char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char[] resultCharArray = new char[byteArray.length * 2];
int index = 0;
for (byte b : byteArray) {
resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];
resultCharArray[index++] = hexDigits[b & 0xf];
}
return new String(resultCharArray);
}
public int getRandom() {
return random.nextInt(999999)%900000+100000;
}
public HttpURLConnection getPostHttpConn(String url) throws Exception {
URL object = new URL(url);
HttpURLConnection conn;
conn = (HttpURLConnection) object.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestMethod("POST");
return conn;
}
public String calculateSig(
String accesskey,
long random,
String msg,
long curTime,
ArrayList phoneNumbers) throws NoSuchAlgorithmException {
String phoneNumbersString = phoneNumbers.get(0);
for (int i = 1; i < phoneNumbers.size(); i++) {
phoneNumbersString += "," + phoneNumbers.get(i);
}
return strToHash(String.format(
"accesskey=%s&random=%d&time=%d&mobile=%s",
accesskey, random, curTime, phoneNumbersString));
}
public String calculateSigForTempl(
String accesskey,
long random,
long curTime,
ArrayList phoneNumbers) throws NoSuchAlgorithmException {
String phoneNumbersString = phoneNumbers.get(0);
for (int i = 1; i < phoneNumbers.size(); i++) {
phoneNumbersString += "," + phoneNumbers.get(i);
}
return strToHash(String.format(
"accesskey=%s&random=%d&time=%d&mobile=%s",
accesskey, random, curTime, phoneNumbersString));
}
public String calculateSigForTempl(
String accesskey,
long random,
long curTime,
String phoneNumber) throws NoSuchAlgorithmException {
ArrayList phoneNumbers = new ArrayList<>();
phoneNumbers.add(phoneNumber);
return calculateSigForTempl(accesskey, random, curTime, phoneNumbers);
}
public JSONArray phoneNumbersToJSONArray(String nationCode, ArrayList phoneNumbers) {
JSONArray tel = new JSONArray();
int i = 0;
do {
JSONObject telElement = new JSONObject();
telElement.put("nationcode", nationCode);
telElement.put("mobile", phoneNumbers.get(i));
tel.put(telElement);
} while (++i < phoneNumbers.size());
return tel;
}
public JSONArray smsParamsToJSONArray(ArrayList params) {
JSONArray smsParams = new JSONArray();
for (int i = 0; i < params.size(); i++) {
smsParams.put(params.get(i));
}
return smsParams;
}
public SmsSingleSenderResult jsonToSmsSingleSenderResult(JSONObject json) {
SmsSingleSenderResult result = new SmsSingleSenderResult();
result.result = json.getInt("result");
result.errMsg = json.getString("errmsg");
if (0 == result.result) {
result.ext = json.getString("ext");
result.sid = json.getString("sid");
result.fee = json.getInt("fee");
}
return result;
}
public SmsStatusPullCallbackResult jsonToSmsStatusPullCallbackrResult(JSONObject json) {
SmsStatusPullCallbackResult result = new SmsStatusPullCallbackResult();
result.result = json.getInt("result");
result.errmsg = json.getString("errmsg");
if (true == json.isNull("data")) {
return result;
}
result.callbacks = new ArrayList<>();
JSONArray datas = json.getJSONArray("data");
for(int index = 0 ; index< datas.length(); index++){
JSONObject cb = datas.getJSONObject(index);
SmsStatusPullCallbackResult.Callback callback = result.new Callback();
callback.user_receive_time = cb.getString("user_receive_time");
callback.nationcode = cb.getString("nationcode");
callback.mobile = cb.getString("mobile");
callback.report_status = cb.getString("report_status");
callback.errmsg = cb.getString("errmsg");
callback.description = cb.getString("description");
callback.sid = cb.getString("sid");
result.callbacks.add(callback);
}
return result;
}
public SmsVoiceVerifyCodeSenderResult jsonToSmsSingleVoiceSenderResult(JSONObject json) {
SmsVoiceVerifyCodeSenderResult result = new SmsVoiceVerifyCodeSenderResult();
result.result = json.getInt("result");
if (false == json.isNull("errmsg")) {
result.errmsg = json.getString("errmsg");
}
if (0 == result.result) {
result.ext = json.getString("ext");
result.callid = json.getString("callid");
}
return result;
}
}
6.SmsSingleSender.java
package com.moduyun.sdk.sms.yun;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.util.ArrayList;
// org.json 第三方库请自行下载编译,或者在以下链接下载使用 jdk 1.7 的版本
// http://share.weiyun.com/630a8c65e9fd497f3687b3546d0b839e
import org.json.JSONObject;
public class SmsSingleSender {
String accesskey;
String secretkey;
//同时支持http和https两种协议,具体根据自己实际情况使用。
String url = "https://live.moduyun.com/sms/v1/sendsinglesms";
SmsSenderUtil util = new SmsSenderUtil();
public SmsSingleSender(String accesskey, String secretkey) throws Exception {
this.accesskey = accesskey;
this.secretkey = secretkey;
}
/**
* 普通单发短信接口,明确指定内容,如果有多个签名,请在内容中以【】的方式添加到信息内容中,否则系统将使用默认签名
* @param type 短信类型,0 为普通短信,1 营销短信
* @param nationCode 国家码,如 86 为中国
* @param phoneNumber 不带国家码的手机号
* @param msg 信息内容,必须与申请的模板格式一致,否则将返回错误
* @param extend 扩展码,可填空
* @param ext 服务端原样返回的参数,可填空
* @return {@link}SmsSingleSenderResult
* @throws Exception
*/
public SmsSingleSenderResult send(
int type,
String nationCode,
String phoneNumber,
String msg,
String extend,
String ext) throws Exception {
/*
请求包体
{
"tel": {
"nationcode": "86",
"mobile": "13788888888"
},
"type": 0,
"msg": "你的验证码是1234",
"sig": "fdba654e05bc0d15796713a1a1a2318c",
"time": 1479888540,
"extend": "",
"ext": ""
}
应答包体
{
"result": 0,
"errmsg": "OK",
"ext": "",
"sid": "xxxxxxx",
"fee": 1
}
*/
// 校验 type 类型
if (0 != type && 1 != type) {
throw new Exception("type " + type + " error");
}
if (null == extend) {
extend = "";
}
if (null == ext) {
ext = "";
}
// 按照协议组织 post 请求包体
long random = util.getRandom();
long curTime = System.currentTimeMillis()/1000;
JSONObject data = new JSONObject();
JSONObject tel = new JSONObject();
tel.put("nationcode", nationCode);
tel.put("mobile", phoneNumber);
data.put("type", type);
data.put("msg", msg);
data.put("sig", util.strToHash(String.format(
"secretkey=%s&random=%d&time=%d&mobile=%s",
secretkey, random, curTime, phoneNumber)));
data.put("tel", tel);
data.put("time", curTime);
data.put("extend", extend);
data.put("ext", ext);
// 与上面的 random 必须一致
String wholeUrl = String.format("%s?accesskey=%s&random=%d", url, accesskey, random);
HttpURLConnection conn = util.getPostHttpConn(wholeUrl);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
wr.write(data.toString());
wr.flush();
System.out.println(data.toString());
// 显示 POST 请求返回的内容
StringBuilder sb = new StringBuilder();
int httpRspCode = conn.getResponseCode();
SmsSingleSenderResult result;
if (httpRspCode == HttpURLConnection.HTTP_OK) {
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
System.out.println(sb.toString());
JSONObject json = new JSONObject(sb.toString());
result = util.jsonToSmsSingleSenderResult(json);
} else {
result = new SmsSingleSenderResult();
result.result = httpRspCode;
result.errMsg = "http error " + httpRspCode + " " + conn.getResponseMessage();
}
return result;
}
/**
* 指定模板单发
* @param nationCode 国家码,如 86 为中国
* @param phoneNumber 不带国家码的手机号
* @param templId 信息内容
* @param params 模板参数列表,如模板 {1}...{2}...{3},那么需要带三个参数
* @param sign 签名,如果填空,系统会使用默认签名
* @param extend 扩展码,可填空
* @param ext 服务端原样返回的参数,可填空
* @return {@link}SmsSingleSenderResult
* @throws Exception
*/
public SmsSingleSenderResult sendWithParam(
String nationCode,
String phoneNumber,
int templId,
ArrayList params,
String sign,
String extend,
String ext) throws Exception {
/*
请求包体
{
"tel": {
"nationcode": "86",
"mobile": "13788888888"
},
"sign": "Kewail云",
"tpl_id": 19,
"params": [
"验证码",
"1234",
"4"
],
"sig": "fdba654e05bc0d15796713a1a1a2318c",
"time": 1479888540,
"extend": "",
"ext": ""
}
应答包体
{
"result": 0,
"errmsg": "OK",
"ext": "",
"sid": "xxxxxxx",
"fee": 1
}
*/
if (null == nationCode || 0 == nationCode.length()) {
nationCode = "86";
}
if (null == params) {
params = new ArrayList<>();
}
if (null == sign) {
sign = "";
}
if (null == extend) {
extend = "";
}
if (null == ext) {
ext = "";
}
long random = util.getRandom();
long curTime = System.currentTimeMillis()/1000;
JSONObject data = new JSONObject();
JSONObject tel = new JSONObject();
tel.put("nationcode", nationCode);
tel.put("mobile", phoneNumber);
data.put("tel", tel);
data.put("sig", util.calculateSigForTempl(secretkey, random, curTime, phoneNumber));
data.put("tpl_id", templId);
data.put("params", util.smsParamsToJSONArray(params));
data.put("sign", sign);
data.put("time", curTime);
data.put("extend", extend);
data.put("ext", ext);
String wholeUrl = String.format("%s?accesskey=%d&random=%d", url, accesskey, random);
HttpURLConnection conn = util.getPostHttpConn(wholeUrl);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
wr.write(data.toString());
wr.flush();
// 显示 POST 请求返回的内容
StringBuilder sb = new StringBuilder();
int httpRspCode = conn.getResponseCode();
SmsSingleSenderResult result;
if (httpRspCode == HttpURLConnection.HTTP_OK) {
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
JSONObject json = new JSONObject(sb.toString());
result = util.jsonToSmsSingleSenderResult(json);
} else {
result = new SmsSingleSenderResult();
result.result = httpRspCode;
result.errMsg = "http error " + httpRspCode + " " + conn.getResponseMessage();
}
return result;
}
}
7.SmsSingleSenderResult.java
package com.moduyun.sdk.sms.yun;
public class SmsSingleSenderResult {
/*
{
"result": 0,
"errmsg": "OK",
"ext": "",
"sid": "xxxxxxx",
"fee": 1
}
*/
public int result;
public String errMsg = "";
public String ext = "";
public String sid = "";
public int fee;
public String toString() {
return String.format(
"SmsSingleSenderResult\nresult %d\nerrMsg %s\next %s\nsid %s\nfee %d",
result, errMsg, ext, sid, fee);
}
}
8.SmsStatusPullCallbackResult.java
package com.moduyun.sdk.sms.yun;
import java.util.ArrayList;
public class SmsStatusPullCallbackResult {
class Callback{
String user_receive_time;
String nationcode;
String mobile;
String report_status;
String errmsg;
String description;
String sid;
public String toString(){
return String.format("\t"
+"user_receive_time:%s\t"
+"nationcode:%s\t"
+"mobile:%s\t"
+"errmsg:%s\t"
+"report_status:%s\t"
+"description:%s\t"
+"sid:%s\t",
user_receive_time,
nationcode,
mobile,
report_status,
errmsg,
description,
sid
);
}
}
int result;
String errmsg;
int count;
ArrayList callbacks;
public String toString() {
return String.format("SmsStatusPullCallbackResult:\n"
+"result:%d\n"
+"errmsg:%s\n"
+"count:%d\n"
+"callbacks:%s\n",
result,
errmsg,
count,
callbacks.toString()
);
}
}
到此完整代码已经结束。最后要做的,就是到:短信服务--->接口短信--->签名管理和内容管理这两个栏目添加签名和提交报备模板即可。
提交短信的时候把内容替换成需要发送的模板如:msg=【签名】+具体内容。