在印度市场构建应用程序时,短信仍然是连接用户最可靠的方式。无论是OTP验证、订单通知,还是营销提醒,一个稳定、合规的SMS API是每款应用的必备基础设施。
本文将为开发者提供一份从零开始的**印度短信API接口**接入指南,涵盖**印度短信API接入**的全部关键步骤,并提供Python、Java、PHP三种语言的完整代码示例。无论你使用哪种技术栈,都能快速上手。
**印度短信API**是一种允许应用程序通过HTTP/HTTPS协议调用短信网关的程序化接口。当你的应用触发某个事件(如用户点击“发送验证码”)时,API会捕获该请求,按照运营商规范进行格式化,校验DLT模板合规性,然后将短信发送到运营商的短信中心(SMSC)。
所有流程在几秒内完成,你的代码只需发起一次HTTP请求即可。
SMS API为开发者带来的核心价值体现在四个层面:
- **自动化**:基于业务触发条件自动发送,无需人工操作
- **规模化**:通过队列机制处理数千甚至上万的并发请求
- **可追溯**:每条消息均可记录、审计,支持实时报表
- **合规化**:自动携带DLT所需的发送方ID和模板ID,确保每条消息符合TRAI规定
在调用**短信接口调用**之前,首先需要在短信服务商平台完成注册。以印度主流服务商为例:
1. **注册账号**:访问服务商官网(如SpringEdge、Msg91、SMSGatewayCenter等),填写企业信息完成注册
2. **获取API密钥**:登录控制台,在API管理或开发者设置中生成API Key(通常为Bearer Token格式)
3. **充值或获取免费额度**:大多数服务商支持按量付费或套餐包购买,部分提供免费试用额度
在印度发送商业短信,**DLT(分布式账本技术)合规是强制性的**。TRAI要求所有发送商业短信的企业必须完成实体注册、发送方ID备案和模板审核。
如果你的API请求中缺少以下信息,短信将被运营商直接拦截:
- **DLT实体ID(Entity ID)** :企业完成注册后获得的唯一标识
- **发送方ID(Sender ID)** :品牌名称,通常为6个字符以内的字母组合
- **模板ID(Template ID)** :短信内容模板在DLT系统中备案后获得的ID
服务商会协助完成模板备案和发送方ID注册,开发者只需要在API请求中传入这些参数即可。
以下是印度主流的短信API服务商对比:
| 服务商 | 特点 | 适合场景 | API类型 |
| :--- | :--- | :--- | :--- |
| **SpringEdge** | RESTful API,支持RCS,DLT全自动处理,99.99%可用性 | OTP验证、跨国通信 | HTTP/REST |
| **Msg91** | CPaaS平台,支持SMS/WhatsApp/RCS,多语言SDK | 多通道企业级通信 | HTTP/REST + SDK |
| **SMSGatewayCenter** | 提供PHP、Java、C、Python多语言代码示例,24/7支持 | 中小企业快速集成 | HTTP/REST + SMPP |
| **SSD Web Solutions** | 简单HTTP API,无SDK锁定,IP白名单安全控制 | 小型开发者/创业团队 | HTTP/REST |
| **Textlocal** | 老牌服务商,提供多种语言示例代码 | 成熟企业用户 | HTTP/REST |
无论选择哪家服务商,**短信API接口**的核心参数通常包括以下字段:
| 参数名 | 类型 | 必填 | 说明 |
| :--- | :--- | :--- | :--- |
| `apikey` / `authkey` | string | 是 | 身份认证密钥 |
| `sender` / `from` | string | 是 | 发送方ID(DLT注册后的品牌名称) |
| `mobile` / `to` | string | 是 | 接收方手机号,格式:91xxxxxxxxxx(印度国家代码91) |
| `message` / `text` | string | 是 | 短信内容(需URL编码) |
| `template_id` | string | 否* | DLT模板ID(发送DLT短信时必填) |
| `entity_id` | string | 否* | DLT实体ID(发送DLT短信时必填) |
| `route` / `msg_type` | string | 否 | 路由类型:transactional/promotional |
> *注:根据TRAI的DLT规定,发送交易短信或促销短信时必须携带template_id和entity_id,否则运营商网关会直接拦截。
大多数服务商采用标准的RESTful API设计,请求方式为`GET`或`POST`,响应格式为JSON。
GET方式示例
```
https://api.provider.com/send?apikey=YOUR_API_KEY&sender=YOUR_SENDER_ID&mobile=919876543210&message=Hello&template_id=123456
```
POST方式示例(JSON Body)
```json
{
"apikey": "YOUR_API_KEY",
"sender": "YOUR_SENDER_ID",
"mobile": "919876543210",
"message": "Your OTP is 654321",
"template_id": "1234567890",
"entity_id": "ABCD1234"
}
```
成功响应示例
```json
{
"status": "success",
"message_id": "abc123def456",
"credits_used": 1
}
```
失败响应示例
```json
{
"status": "error",
"code": "INVALID_API_KEY",
"message": "Authentication failed"
}
```
```python
import requests
import urllib.parse
API配置
API_KEY = "YOUR_API_KEY"
SENDER_ID = "YOUR_SENDER_ID"
TEMPLATE_ID = "YOUR_TEMPLATE_ID" DLT备案后的模板ID
ENTITY_ID = "YOUR_ENTITY_ID" DLT实体ID
API_URL = "https://api.springedge.com/v1/sms/send" 以SpringEdge为例
发送短信函数
def send_sms(mobile_number, message):
对消息内容进行URL编码(支持中文和印度本地语言)
encoded_message = urllib.parse.quote(message)
构造请求参数
params = {
'apikey': API_KEY,
'sender': SENDER_ID,
'mobile': mobile_number,
'message': encoded_message,
'template_id': TEMPLATE_ID,
'entity_id': ENTITY_ID,
'type': 'transactional' 或 'promotional'
}
try:
response = requests.post(API_URL, data=params, timeout=10)
result = response.json()
if response.status_code == 200 and result.get('status') == 'success':
print(f"短信发送成功! Message ID: {result.get('message_id')}")
return True
else:
print(f"发送失败: {result.get('message')}")
return False
except requests.exceptions.RequestException as e:
print(f"请求异常: {e}")
return False
使用示例
if __name__ == "__main__":
send_sms("919876543210", "Your OTP is 654321")
```
```python
from concurrent.futures import ThreadPoolExecutor
import threading
线程安全的计数器
sent_count = 0
failed_count = 0
lock = threading.Lock()
def send_batch_sms(mobile_list, message):
global sent_count, failed_count
for mobile in mobile_list:
result = send_sms(mobile, message)
with lock:
if result:
sent_count += 1
else:
failed_count += 1
批量发送示例
mobile_numbers = ["919876543210", "919876543211", "919876543212"] 最多支持10万+条
with ThreadPoolExecutor(max_workers=5) as executor:
executor.submit(send_batch_sms, mobile_numbers, "Your OTP is 654321")
```
```java
import okhttp3.*;
import java.io.IOException;
public class SMSClient {
private static final String API_URL = "https://api.springedge.com/v1/sms/send";
private static final String API_KEY = "YOUR_API_KEY";
private static final String SENDER_ID = "YOUR_SENDER_ID";
private static final String TEMPLATE_ID = "YOUR_TEMPLATE_ID";
private static final String ENTITY_ID = "YOUR_ENTITY_ID";
private final OkHttpClient client = new OkHttpClient();
public boolean sendSms(String mobileNumber, String message) throws IOException {
// 使用OkHttp构建POST请求
RequestBody body = new FormBody.Builder()
.add("apikey", API_KEY)
.add("sender", SENDER_ID)
.add("mobile", mobileNumber)
.add("message", message)
.add("template_id", TEMPLATE_ID)
.add("entity_id", ENTITY_ID)
.add("type", "transactional")
.build();
Request request = new Request.Builder()
.url(API_URL)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
String responseBody = response.body().string();
System.out.println("Response: " + responseBody);
return response.isSuccessful();
}
}
// 使用示例
public static void main(String[] args) {
SMSClient smsClient = new SMSClient();
try {
smsClient.sendSms("919876543210", "Your OTP is 654321");
} catch (IOException e) {
System.err.println("发送失败: " + e.getMessage());
}
}
}
```
```java
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class SMSClientApache {
public void sendSmsWithApache(String mobile, String message) throws Exception {
String url = "https://api.provider.com/send";
// 构建JSON请求体
String jsonBody = String.format(
"{\"apikey\":\"%s\",\"sender\":\"%s\",\"mobile\":\"%s\",\"message\":\"%s\",\"template_id\":\"%s\"}",
"YOUR_API_KEY", "YOUR_SENDER_ID", mobile, message, "YOUR_TEMPLATE_ID"
);
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Content-Type", "application/json");
httpPost.setEntity(new StringEntity(jsonBody));
try (CloseableHttpClient client = HttpClients.createDefault()) {
var response = client.execute(httpPost);
String result = EntityUtils.toString(response.getEntity());
System.out.println("发送结果: " + result);
}
}
}
```
```php
// API配置
$api_key = "YOUR_API_KEY";
$sender_id = "YOUR_SENDER_ID";
$template_id = "YOUR_TEMPLATE_ID";
$entity_id = "YOUR_ENTITY_ID";
$api_url = "https://api.provider.com/send";
// 发送短信函数
function sendSMS($mobile, $message, $api_key, $sender_id, $template_id, $entity_id, $api_url) {
// URL编码消息内容(支持中文/印地语)
$encoded_message = urlencode($message);
// 构造请求参数
$params = http_build_query([
'apikey' => $api_key,
'sender' => $sender_id,
'mobile' => $mobile,
'message' => $encoded_message,
'template_id' => $template_id,
'entity_id' => $entity_id,
'type' => 'transactional'
]);
// 使用cURL发送请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code == 200) {
$result = json_decode($response, true);
echo "短信发送成功! Message ID: " . $result['message_id'] . "\n";
return true;
} else {
echo "发送失败,HTTP状态码: $http_code\n";
return false;
}
}
// 使用示例
sendSMS("919876543210", "Your OTP is 654321", $api_key, $sender_id, $template_id, $entity_id, $api_url);
?>
```
Laravel 8.0及以上版本提供了更优雅的HTTP客户端实现:
```php
use Illuminate\Support\Facades\Http;
class SmsService
{
protected $apiKey;
protected $senderId;
protected $templateId;
protected $entityId;
public function __construct()
{
$this->apiKey = config('sms.api_key');
$this->senderId = config('sms.sender_id');
$this->templateId = config('sms.template_id');
$this->entityId = config('sms.entity_id');
}
public function sendOtp($mobile, $otp)
{
$response = Http::post('https://api.provider.com/send', [
'apikey' => $this->apiKey,
'sender' => $this->senderId,
'mobile' => $mobile,
'message' => "Your OTP is: $otp",
'template_id' => $this->templateId,
'entity_id' => $this->entityId,
'type' => 'transactional'
]);
if ($response->successful()) {
return $response->json();
}
throw new \Exception('SMS发送失败: ' . $response->body());
}
}
```
大多数服务商支持通过Webhook将短信的送达状态实时推送至你的服务器。
1. 在服务商控制台中配置回调URL:`https://yourdomain.com/api/sms/delivery-callback`
2. 服务商在短信状态更新时(送达、失败、过期)会向该URL发送POST请求
3. 你的服务器接收并处理回调数据,更新数据库中的短信状态
```php
// Webhook接收端点
$payload = file_get_contents('php://input');
$data = json_decode($payload, true);
if ($data) {
$message_id = $data['message_id'];
$status = $data['status']; // delivered / failed / expired
$error_code = $data['error_code'] ?? null;
// 更新数据库中的短信状态
update_sms_status($message_id, $status, $error_code);
http_response_code(200);
echo "OK";
}
?>
```
- 验证请求来源IP是否在服务商官方IP白名单内
- 验证请求签名(如服务商提供签名机制)
- 使用HTTPS端点确保传输加密
| 错误码/现象 | 可能原因 | 解决方案 |
| INVALID_API_KEY | API密钥无效或过期 | 登录控制台重新生成API Key |
| INVALID_SENDER_ID | 发送方ID未备案或格式错误 | 确认Sender ID为6个字符内的字母组合,并已在DLT系统备案 |
| TEMPLATE_NOT_APPROVED | 模板未通过DLT审核 | 在DLT平台提交模板审核,审核通过后使用正确的template_id |
| DND_FILTERED | 收件人注册了DND(免打扰)且发送的是促销短信 | 促销短信无法突破DND限制,改用交易短信通道或引导用户退订DND |
| INSUFFICIENT_BALANCE | 账户余额不足 | 充值后重试 |
| 送达回执显示失败 | 收件人号码无效或运营商网关异常 | 使用服务商控制台查看详细错误码,或联系技术支持 |
- **批量发送**:单次API调用支持最多10,000个收件人,减少网络往返
- **异步队列**:将短信发送任务放入消息队列(如RabbitMQ、Redis Queue),避免阻塞主业务流程
- **连接池**:Java应用中复用HTTP连接池(如OkHttpClient单例),减少连接建立开销
- **超时设置**:合理配置连接超时(3秒)和读取超时(10秒),避免长时间等待
发送短信至印度手机号时,**必须包含印度国家代码91,且不要包含前导的‘+’号或‘00’**。正确的格式示例:`919876543210。
短信内容包含Unicode字符(中文、印地语、泰米尔语等)时,字符限制从160字符降为70字符,超出部分会分段计费。在API调用时,确保对消息内容进行**URL编码**(urllib.parse.quote或urlencode),否则特殊字符可能被网关错误解析。
在正式环境中,不能仅仅发送完就结束。可靠的实现通常包括三个层次:**重试机制**(首次失败后自动重试2-3次)、**降级通道**(主通道不可用时自动切换备用服务商)、以及**用户侧提示**(APP端显示“验证码发送中,请稍后重试”的友好提示)。
**印度短信API接口**的选择取决于具体业务场景:
| 业务场景 | 推荐方案 | 关键考量 |
| OTP验证码 | SpringEdge / Msg91 | 要求<3秒送达、自动重试和降级机制 |
| 交易通知 | SMSGatewayCenter / SSD Web | 要求高送达率、真实DLR、DLT合规支持 |
| 营销推广 | Textlocal / Fast2SMS | 促销通道价格更优,支持批量发送和定时任务 |
| 多通道整合 | Msg91 / Tanla | 同时需要SMS、WhatsApp、RCS等通道的CPaaS平台 |
| 高并发场景 | Karix / Tanla | 企业级SMPP连接,承载运营商级流量 |
本文详细介绍了**印度短信API接口**的接入方法,涵盖Python、Java、PHP三种语言的完整代码示例。SMS API的本质是HTTP/REST调用,但真正可靠的生产级实现需要在代码之外做更多功课:DLT合规、送达回执处理、失败重试机制、多服务商冗余。
建议在正式上线前,先通过小批量测试验证API的稳定性和送达率,再逐步切换到全量生产环境。良好的API设计不仅要“发得出去”,更要“发得稳、发得到、发得合规”。