JAVA实现国际短信验证码发送接口的完整指南

本文将详细介绍如何使用JAVA语言快速接入国际短信API接口,实现国际验证码短信的发送功能,拿来就能用,10分钟就能完成接入
你好测试abc
354812298791aasx
主要提供两大功能:你好World2023*
单条短信发送(支持黑名单等拦截错误实时返回)354812298791aasx
获取状态报告(每条短信状态仅可获取一次)
Random你好456
你好World2023*
完整java代码实现World测试789
以下是完整的java示例代码,只需替换配置参数即可使用:
你好测试abc
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.com国际短信接口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) { Listreports = 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 reports; private String data; public ReportResult(boolean success, String message, List 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 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()); // } }}
使用说明
1. 配置参数
在使用代码前,需要修改以下配置参数:
private static final String SP_ID = "908452"; // 替换为您的SP_IDprivate static final String RAW_PASSWORD = "your_raw_password"; // 替换为您的原始密码
2. 发送验证码短信
// 准备参数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 = InternationalSMSDemo.sendVerificationCode(mobile, message, "");// 处理结果if (result.isSuccess()) { // 发送成功,保存msg_id到数据库 String msgId = result.getMsgId(); System.out.println("短信发送成功!消息ID: " + msgId);} else { // 发送失败,输出错误信息 System.out.println("短信发送失败: " + result.getMessage());}
3. 获取状态报告
// 获取状态报告ReportResult reportResult = InternationalSMSDemo.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());}
注意事项
国际手机号格式:使用国家代码+手机号的格式,不需要添加"+"前缀(例如菲律宾号码:639267890123)
密码处理:代码已自动将密码进行MD5处理,只需提供原始密码即可
状态报告:每条短信的状态报告只能获取一次,获取后需要本地存储
错误处理:代码已包含完整的错误码解析功能,方便定位问题
JSON解析:为了减少依赖,代码使用了简单的字符串处理来解析JSON。在实际项目中,建议使用Jackson或Gson等JSON库
异常处理:代码已包含基本的异常处理,但实际项目中可能需要更完善的错误处理机制
常见问题
Q: 返回"密码错误"怎么办?
A: 请确认提供的原始密码是否正确,系统会自动进行MD5加密。
Q: 如何知道短信是否发送成功?
A: 发送接口会返回即时结果,也可以通过获取状态报告接口查询发送状态。
Q: 支持哪些国家和地区?
A: 智慧云信国际短信平台支持全球多个国家和地区的短信发送,具体可咨询平台客服。
结语
本文提供的Java代码示例可以帮助开发者快速接入智慧云信国际短信接口,实现验证码短信的发送功能。代码已经过优化,包含完整的错误处理和状态报告功能,只需替换配置参数即可使用。