本文将详细介绍如何使用java语言快速接入国际全球验证码短信API接口,实现国际验证码短信的发送功能,拿来就能用,10分钟就能完成接入短信登录、注册、密码找回等功能。
主要提供两大功能:
单条短信发送(支持黑名单等拦截错误实时返回)
获取状态报告(每条短信状态仅可获取一次)
环境要求
有效的SP_ID和密钥(开发者中心查看)
完整java代码实现
以下是完整的java示例代码,只需替换配置参数即可使用:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
/**
* 3yit国际短信接口Java Demo
* 功能:发送国际验证码短信、获取状态报告
* 版本:1.0
*/
public class InternationalSMSDemo {
// ==================== 配置区域 ====================
private static final String SP_ID = "908452"; // 替换为您的SP_ID
private static final String RAW_PASSWORD = "your_raw_password"; // 替换为您的原始密码
private static final String API_SEND_URL = "https://api.3yit.com/api/send-sms-single";
private static final String API_REPORT_URL = "https://api.3yit.com/api/report";
// ==================== 配置结束 ====================
private static final String PASSWORD;
static {
// 自动将密码转换为MD5格式
PASSWORD = md5(RAW_PASSWORD);
}
/**
* 发送单条国际验证码短信
* @param mobile 国际手机号(格式:国家代码+号码,如639257890123)
* @param message 短信内容
* @param ext 扩展号(可选)
* @return 返回结果
*/
public static SMSResult sendVerificationCode(String mobile, String message, String ext) {
try {
// 准备请求参数
String params = "sp_id=" + URLEncoder.encode(SP_ID, "UTF-8") +
"&mobile=" + URLEncoder.encode(mobile, "UTF-8") +
"&content=" + URLEncoder.encode(message, "UTF-8") +
"&password=" + URLEncoder.encode(PASSWORD, "UTF-8") +
(ext != null && !ext.isEmpty() ? "&ext=" + URLEncoder.encode(ext, "UTF-8") : "");
// 发送POST请求
String result = httpPost(API_SEND_URL, params);
// 解析返回的JSON
SMSResult smsResult = parseSendResult(result);
if (smsResult != null) {
return smsResult;
} else {
return new SMSResult(false, "API响应解析失败", result);
}
} catch (Exception e) {
return new SMSResult(false, "发送短信时发生异常: " + e.getMessage(), null);
}
}
/**
* 获取状态报告
* @return 返回状态报告数据
*/
public static ReportResult getReport() {
try {
// 准备请求参数
String params = "sp_id=" + URLEncoder.encode(SP_ID, "UTF-8") +
"&password=" + URLEncoder.encode(PASSWORD, "UTF-8");
String url = API_REPORT_URL + "?" + params;
// 发送GET请求
String result = httpGet(url);
// 解析返回的JSON
return parseReportResult(result);
} catch (Exception e) {
return new ReportResult(false, "获取状态报告时发生异常: " + e.getMessage(), null, null);
}
}
/**
* 发送HTTP POST请求
* @param url 请求地址
* @param params 请求参数
* @return 响应内容
*/
private static String httpPost(String url, String params) {
HttpURLConnection connection = null;
try {
URL apiUrl = new URL(url);
connection = (HttpURLConnection) apiUrl.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setDoOutput(true);
connection.setConnectTimeout(30000);
connection.setReadTimeout(30000);
// 发送请求
try (OutputStream os = connection.getOutputStream()) {
byte[] input = params.getBytes("utf-8");
os.write(input, 0, input.length);
}
// 获取响应
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
StringBuilder response = new StringBuilder();
try (BufferedReader br = new BufferedReader(
new InputStreamReader(connection.getInputStream(), "utf-8"))) {
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
}
return response.toString();
} else {
return "{\"code\":" + responseCode + ",\"msg\":\"HTTP错误:" + responseCode + "\"}";
}
} catch (Exception e) {
return "{\"code\":-1,\"msg\":\"请求异常:" + e.getMessage() + "\"}";
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
/**
* 发送HTTP GET请求
* @param url 请求地址
* @return 响应内容
*/
private static String httpGet(String url) {
HttpURLConnection connection = null;
try {
URL apiUrl = new URL(url);
connection = (HttpURLConnection) apiUrl.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(30000);
connection.setReadTimeout(30000);
// 获取响应
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
StringBuilder response = new StringBuilder();
try (BufferedReader br = new BufferedReader(
new InputStreamReader(connection.getInputStream(), "utf-8"))) {
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
}
return response.toString();
} else {
return "{\"code\":" + responseCode + ",\"msg\":\"HTTP错误:" + responseCode + "\"}";
}
} catch (Exception e) {
return "{\"code\":-1,\"msg\":\"请求异常:" + e.getMessage() + "\"}";
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
/**
* 解析发送结果
* @param json 响应JSON
* @return 发送结果对象
*/
private static SMSResult parseSendResult(String json) {
try {
// 简单JSON解析,实际项目中可以使用JSON库如Jackson或Gson
int codeStart = json.indexOf("\"code\":") + 7;
int codeEnd = json.indexOf(",", codeStart);
if (codeEnd == -1) codeEnd = json.indexOf("}", codeStart);
int code = Integer.parseInt(json.substring(codeStart, codeEnd).trim());
int msgStart = json.indexOf("\"msg\":\"") + 7;
int msgEnd = json.indexOf("\"", msgStart);
String msg = json.substring(msgStart, msgEnd);
if (code == 0) {
int msgIdStart = json.indexOf("\"msg_id\":\"") + 10;
int msgIdEnd = json.indexOf("\"", msgIdStart);
String msgId = json.substring(msgIdStart, msgIdEnd);
return new SMSResult(true, msg, msgId, null);
} else {
String data = null;
if (json.contains("\"data\":")) {
int dataStart = json.indexOf("\"data\":\"") + 8;
int dataEnd = json.indexOf("\"", dataStart);
data = json.substring(dataStart, dataEnd);
}
return new SMSResult(false, getErrorMessage(code, data), null, data);
}
} catch (Exception e) {
return null;
}
}
/**
* 解析报告结果
* @param json 响应JSON
* @return 报告结果对象
*/
private static ReportResult parseReportResult(String json) {
try {
// 简单JSON解析
int codeStart = json.indexOf("\"code\":") + 7;
int codeEnd = json.indexOf(",", codeStart);
if (codeEnd == -1) codeEnd = json.indexOf("}", codeStart);
int code = Integer.parseInt(json.substring(codeStart, codeEnd).trim());
int msgStart = json.indexOf("\"msg\":\"") + 7;
int msgEnd = json.indexOf("\"", msgStart);
String msg = json.substring(msgStart, msgEnd);
if (code == 0) {
List<Report> reports = new ArrayList<>();
if (json.contains("\"data\":\"")) {
int dataStart = json.indexOf("\"data\":\"") + 8;
int dataEnd = json.indexOf("\"", dataStart);
String data = json.substring(dataStart, dataEnd);
if (!data.isEmpty()) {
String[] reportList = data.split("\\|");
for (String report : reportList) {
String[] fields = report.split(",");
if (fields.length >= 5) {
reports.add(new Report(
fields[0],
fields[1],
fields[2],
fields[3],
fields[4],
fields.length > 5 ? fields[5] : ""
));
}
}
}
}
return new ReportResult(true, msg, reports, null);
} else {
return new ReportResult(false, getErrorMessage(code), null, null);
}
} catch (Exception e) {
return new ReportResult(false, "解析报告结果时发生异常: " + e.getMessage(), null, null);
}
}
/**
* MD5加密
* @param input 原始字符串
* @return MD5加密后的字符串
*/
private static String md5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes());
StringBuilder hexString = new StringBuilder();
for (byte b : messageDigest) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (Exception e) {
throw new RuntimeException("MD5加密失败", e);
}
}
/**
* 获取错误信息
* @param code 错误码
* @param data 错误数据
* @return 错误描述
*/
private static String getErrorMessage(int code, String data) {
switch (code) {
case 10000: return "服务出错,请稍后再试";
case 10001: return "参数错误,请确认";
case 10008: return "账号被锁定,请联系管理员确认";
case 10011: return "余额不足,请尽快充值";
case 10100: return "签名校验失败";
case 10101: return "您的ip不在白名单内,请确认";
case 10102: return "密码错误,请确认";
case 10200: return "产品sp_id必须填写";
case 10201: return "手机号必须填写";
case 10202: return "短信内容必须填写";
case 10203: return "发送时间格式必须为UNIX时间戳";
case 10208:
String detail = getDataErrorMessage(data);
return "短信进拦截" + (detail != null ? ": " + detail : "");
case 10209: return "触发防刷,请调整配置";
default: return "未知错误 (代码: " + code + ")";
}
}
/**
* 获取错误信息
* @param code 错误码
* @return 错误描述
*/
private static String getErrorMessage(int code) {
return getErrorMessage(code, null);
}
/**
* 获取数据错误信息
* @param data 错误数据
* @return 错误描述
*/
private static String getDataErrorMessage(String data) {
if (data == null) return null;
switch (data) {
case "WL:MBLJ": return "短信内容匹配到了模板,并且此模板类型是拦截";
case "WL:MBSH": return "命中审核模板";
case "WL:NMLJ": return "短信内容没有匹配到模板,并且用户的模板审核方式是未匹配到就进拦截";
case "WL:NMSH": return "短信内容没有匹配到模板,并且用户的模板审核方式是未匹配到就进审核";
case "WL:KHLJ": return "命中空号,进拦截";
case "WL:QHLJ": return "命中用户签名黑名单,进拦截";
case "WL:SHLJ": return "命中用户SPID黑名单,进拦截";
case "WL:CHLJ": return "命中系统产品黑名单,进拦截";
case "WL:CWHM": return "错误号码";
case "WL:QWBB": return "签名未报备,进拦截";
case "WL:MQM": return "需要签名但没有,进拦截";
case "WL:CS": return "超过限速了";
case "WL:ZJLJ": return "不匹配任何模板,直接拦截";
case "WL:CMT": return "产品未配置相应通道,进拦截";
case "WL:CDQC": return "通道不支持该地区发送,进拦截";
case "WL:CGMT": return "产品通道池中没有相应通道,进拦截";
case "WL:CNH": return "所选的通道不健康,进拦截";
case "WL:TCLJ": return "不在发送时间段,进拦截";
case "WL:TCSH": return "不在发送时间段,进审核";
case "WL:CPL": return "超频限制";
default: return null;
}
}
/**
* 短信发送结果类
*/
public static class SMSResult {
private boolean success;
private String message;
private String msgId;
private String data;
public SMSResult(boolean success, String message, String msgId, String data) {
this.success = success;
this.message = message;
this.msgId = msgId;
this.data = data;
}
public SMSResult(boolean success, String message, String data) {
this(success, message, null, data);
}
public boolean isSuccess() { return success; }
public String getMessage() { return message; }
public String getMsgId() { return msgId; }
public String getData() { return data; }
}
/**
* 状态报告结果类
*/
public static class ReportResult {
private boolean success;
private String message;
private List<Report> reports;
private String data;
public ReportResult(boolean success, String message, List<Report> reports, String data) {
this.success = success;
this.message = message;
this.reports = reports;
this.data = data;
}
public boolean isSuccess() { return success; }
public String getMessage() { return message; }
public List<Report> getReports() { return reports; }
public String getData() { return data; }
}
/**
* 状态报告类
*/
public static class Report {
private String ext;
private String msgId;
private String mobile;
private String status;
private String time;
private String price;
public Report(String ext, String msgId, String mobile, String status, String time, String price) {
this.ext = ext;
this.msgId = msgId;
this.mobile = mobile;
this.status = status;
this.time = time;
this.price = price;
}
public String getExt() { return ext; }
public String getMsgId() { return msgId; }
public String getMobile() { return mobile; }
public String getStatus() { return status; }
public String getTime() { return time; }
public String getPrice() { return price; }
}
/**
* 使用示例
*/
public static void main(String[] args) {
// 示例1:发送验证码短信
String mobile = "639257890123"; // 国际手机号(菲律宾示例)
int verificationCode = (int) (Math.random() * 9000) + 1000; // 生成随机验证码
String message = "Your verification code is " + verificationCode + ". Please use it within 10 minutes.";
SMSResult result = sendVerificationCode(mobile, message, "");
if (result.isSuccess()) {
System.out.println("短信发送成功!消息ID: " + result.getMsgId());
// 这里应该将msg_id保存到数据库,与用户关联
} else {
System.out.println("短信发送失败: " + result.getMessage());
}
// 示例2:获取状态报告
// ReportResult reportResult = getReport();
// if (reportResult.isSuccess()) {
// System.out.println("获取到 " + reportResult.getReports().size() + " 条状态报告");
// for (Report report : reportResult.getReports()) {
// System.out.println("手机号: " + report.getMobile() +
// ", 状态: " + report.getStatus() +
// ", 时间: " + report.getTime());
// }
// } else {
// System.out.println("获取状态报告失败: " + reportResult.getMessage());
// }
}
}
注意事项
国际手机号格式:使用国家代码+手机号的格式,不需要添加"+"前缀(例如菲律宾号码:639256890123)
密码处理:代码已自动将密码进行MD5处理,只需提供原始密码即可
状态报告:每条短信的状态报告只能获取一次,获取后需要本地存储
错误处理:代码已包含完整的错误码解析功能,方便定位问题
JSON解析:为了减少依赖,代码使用了简单的字符串处理来解析JSON。在实际项目中,建议使用Jackson或Gson等JSON库
异常处理:代码已包含基本的异常处理,但实际项目中可能需要更完善的错误处理机制
常见问题
Q: 返回"密码错误"怎么办?
A: 请确认提供的原始密码是否正确,系统会自动进行MD5加密。
Q: 如何知道短信是否发送成功?
A: 发送接口会返回即时结果,也可以通过获取状态报告接口查询发送状态。
Q: 支持哪些国家和地区?
A: 智慧云信支持全球多个国家和地区的短信发送,具体可咨询平台客服。
结语
本文提供的Java代码示例可以帮助开发者快速接入全球验证码短信接口,实现验证码短信的发送功能。代码已经过优化,包含完整的错误处理和状态报告功能,只需替换配置参数即可使用。
在实际项目中,您可能需要根据业务需求进一步完善代码,例如添加数据库操作、队列处理、日志记录等功能。希望本文对您的开发工作有所帮助!