Java与JS调用联通短信接口全攻略:技术实现与最佳实践
2025.09.17 15:05浏览量:0简介:本文详细解析Java与JavaScript调用联通短信接口的技术实现方案,涵盖接口对接流程、安全认证机制、代码示例及异常处理策略,帮助开发者快速构建稳定可靠的短信服务系统。
一、联通短信接口技术架构解析
联通短信接口采用RESTful API设计规范,提供HTTP/HTTPS协议接入方式。接口核心功能包括短信发送、状态报告查询、余额查询三大模块,支持验证码、通知类、营销类短信的灵活配置。
1.1 接口认证机制
联通采用API Key+Secret的双因子认证体系,开发者需在联通云平台申请独立账号。认证流程包含:
- 申请应用获取AppID和AppKey
- 生成时间戳(精确到秒)
- 构建签名串(SHA256加密)
- 添加认证头信息(Authorization字段)
签名算法示例:
public String generateSign(String appKey, String secret, String timestamp) {
String raw = appKey + secret + timestamp;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(raw.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(digest);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("加密算法异常", e);
}
}
1.2 请求参数规范
核心参数包括:
to
:接收号码(支持批量发送,逗号分隔)content
:短信内容(需进行URL编码)sign
:短信签名(需提前报备)templateId
:模板ID(使用模板时必填)extend
:扩展码(用于状态回传)
二、Java实现方案详解
2.1 基础环境配置
添加HTTP客户端依赖(以Apache HttpClient为例):
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
封装基础请求类:
public class LtsClient {
private static final String API_URL = "https://api.10646.cn/sms/v2/send";
private String appId;
private String appKey;
private String secret;
public LtsClient(String appId, String appKey, String secret) {
this.appId = appId;
this.appKey = appKey;
this.secret = secret;
}
public String sendSms(String to, String content) throws Exception {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(API_URL);
// 构建请求参数
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String sign = generateSign(appKey, secret, timestamp);
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("appId", appId));
params.add(new BasicNameValuePair("to", to));
params.add(new BasicNameValuePair("content", URLEncoder.encode(content, "UTF-8")));
params.add(new BasicNameValuePair("timestamp", timestamp));
params.add(new BasicNameValuePair("sign", sign));
httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
return EntityUtils.toString(response.getEntity());
}
}
}
2.2 高级功能实现
异步发送优化
采用线程池处理批量发送:
ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<String>> futures = new ArrayList<>();
for (String phone : phoneList) {
futures.add(executor.submit(() -> ltsClient.sendSms(phone, "验证码:1234")));
}
// 等待所有任务完成
for (Future<String> future : futures) {
try {
System.out.println(future.get());
} catch (Exception e) {
// 异常处理
}
}
状态回传处理
实现回调接口接收状态报告:
@RestController
@RequestMapping("/sms")
public class SmsCallbackController {
@PostMapping("/status")
public ResponseEntity<String> handleStatus(@RequestBody SmsStatusReport report) {
// 1. 验证签名
if (!verifySign(report.getSign())) {
return ResponseEntity.badRequest().body("签名验证失败");
}
// 2. 更新本地状态
smsService.updateStatus(report.getMsgId(), report.getStatus());
return ResponseEntity.ok("SUCCESS");
}
private boolean verifySign(String sign) {
// 实现签名验证逻辑
return true;
}
}
三、JavaScript实现方案
3.1 浏览器端实现
基础发送示例
async function sendSms(phone, content) {
const appId = 'YOUR_APP_ID';
const appKey = 'YOUR_APP_KEY';
const secret = 'YOUR_SECRET';
const timestamp = Math.floor(Date.now() / 1000);
// 生成签名
const raw = appKey + secret + timestamp;
const sign = CryptoJS.SHA256(raw).toString(CryptoJS.enc.Base64);
try {
const response = await fetch('https://api.10646.cn/sms/v2/send', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
appId,
to: phone,
content: encodeURIComponent(content),
timestamp,
sign
})
});
return await response.json();
} catch (error) {
console.error('发送失败:', error);
throw error;
}
}
前端安全优化
签名计算移至后端:
// 前端调用后端API
async function secureSend(phone) {
const verificationCode = generateCode(); // 生成6位验证码
try {
const response = await fetch('/api/send-sms', {
method: 'POST',
body: JSON.stringify({ phone, content: `验证码:${verificationCode}` })
});
if (response.ok) {
// 启动倒计时
startCountdown(60);
}
} catch (error) {
showError('发送失败');
}
}
3.2 Node.js后端实现
服务端完整示例
const express = require('express');
const axios = require('axios');
const crypto = require('crypto');
const app = express();
app.use(express.json());
const CONFIG = {
API_URL: 'https://api.10646.cn/sms/v2/send',
APP_ID: 'YOUR_APP_ID',
APP_KEY: 'YOUR_APP_KEY',
SECRET: 'YOUR_SECRET'
};
function generateSign(appKey, secret, timestamp) {
const hash = crypto.createHash('sha256');
hash.update(appKey + secret + timestamp);
return hash.digest('base64');
}
app.post('/api/send-sms', async (req, res) => {
const { phone, content } = req.body;
const timestamp = Math.floor(Date.now() / 1000);
const sign = generateSign(CONFIG.APP_KEY, CONFIG.SECRET, timestamp);
try {
const response = await axios.post(CONFIG.API_URL, null, {
params: {
appId: CONFIG.APP_ID,
to: phone,
content: encodeURIComponent(content),
timestamp,
sign
}
});
res.json(response.data);
} catch (error) {
console.error('短信发送失败:', error.response?.data || error.message);
res.status(500).json({ error: '短信发送失败' });
}
});
app.listen(3000, () => console.log('Server running on port 3000'));
四、最佳实践与异常处理
4.1 性能优化建议
- 连接池管理:使用HttpClient连接池复用TCP连接
- 批量发送:单次请求支持最多1000个号码
- 异步处理:采用消息队列解耦发送与业务逻辑
4.2 常见错误处理
错误码 | 描述 | 解决方案 |
---|---|---|
401 | 认证失败 | 检查AppKey/Secret是否正确 |
403 | 签名错误 | 核对签名算法和时间戳 |
429 | 频率限制 | 实现指数退避重试机制 |
500 | 服务端错误 | 检查请求参数完整性 |
4.3 安全防护措施
- IP白名单限制
- 请求频率限制(建议QPS≤10)
- 敏感操作二次验证
- 定期更换API Key
五、部署与监控方案
5.1 日志记录规范
// 使用SLF4J记录关键日志
private static final Logger logger = LoggerFactory.getLogger(LtsClient.class);
public String sendSms(...) {
try {
logger.info("开始发送短信,接收号码:{}", to);
// ...发送逻辑
logger.info("短信发送成功,响应:{}", response);
return response;
} catch (Exception e) {
logger.error("短信发送失败,号码:{},错误:{}", to, e.getMessage());
throw e;
}
}
5.2 监控指标建议
- 发送成功率(成功数/总发送数)
- 平均响应时间(P90/P99)
- 渠道健康度(各运营商成功率对比)
- 余额预警(剩余条数低于阈值时告警)
六、进阶功能实现
6.1 模板短信管理
public class TemplateManager {
private Map<String, String> templateCache = new ConcurrentHashMap<>();
public String getTemplateContent(String templateId, Map<String, String> params) {
return templateCache.computeIfAbsent(templateId, id -> {
// 从数据库或配置文件加载模板
return loadTemplateFromDB(id);
}).replace("${code}", params.get("code"))
.replace("${expire}", params.get("expire"));
}
private String loadTemplateFromDB(String templateId) {
// 实现数据库查询逻辑
return "您的验证码是${code},有效期${expire}分钟";
}
}
6.2 国际化支持
public class I18nSmsSender {
private Map<String, LocaleConfig> localeConfigs;
public void sendInternationalSms(String phone, String templateId, Locale locale) {
LocaleConfig config = localeConfigs.get(locale.getLanguage());
String content = templateManager.getTemplateContent(
templateId,
Map.of("code", generateCode(), "locale", locale.toString())
);
// 根据国家代码选择通道
String countryCode = phone.substring(0, 2);
String gateway = config.getGateways().get(countryCode);
// 发送逻辑...
}
}
七、总结与展望
联通短信接口的Java/JS实现需要重点关注认证安全、性能优化和异常处理三大方面。建议开发者:
- 建立完善的签名验证机制
- 实现异步发送和状态回传处理
- 部署全面的监控告警系统
- 定期进行压力测试和安全审计
未来发展方向包括:5G消息(RCS)集成、AI内容审核、多通道智能路由等。通过持续优化接口调用方案,可显著提升短信送达率和用户体验,为企业通信提供坚实保障。
发表评论
登录后可评论,请前往 登录 或 注册