# 短信对外API接口文档

这是一份短信发送API接口的技术文档，提供了如何通过HTTP接口向用户发送短信的详细说明。本文档包含接口调用方法、参数说明、状态码解释以及各种请求场景的实例，适用于需要在应用中集成短信发送功能的开发人员。

# 文档更新记录

| 版本  | 描述                                     | 作者 | 时间       |
|------|-----------------------------------------|------|------------|
| v1.3 | 1. 增加错误code=110<br>2. 清理增加Java，PHP转16进制示例代码 | | 2020/10/26<br>2021/06/24 |
| v1.4 | 支持https协议                              | | |
| v1.4.1 | [增加客户上报短信状态接口](/books/message-cn-api/page/bd4c9 "增加客户上报短信状态接口")| | |
| v1.4.2 | [增加短信字符编码检查接口](/books/message-cn-api/page/6ea2e "增加短信字符编码检查接口")| | |

# 接口说明

__重要说明：__
1. 发送内容(utf8编码)需转换为16进制码再发送，例如 "你好" 转为 "e4bda0e5a5bd" [跳转到示例代码](/books/message-cn-api/page/java16#2)
2. 手机号需加上国际区码（如：00628131565741）
3. pwd 加密规则为：md5(spid+"00000000"+"明文密码"+timestamp) 如：

   md5前：testspid00000000testpwd1601029303
   
   md5后：a14e201f22aafbae74c4d72030ad5a8d

# 单条短信发送

### 请求URL
```
https://{domain}/sms/send?spid=xx&pwd=xx&das=xx&timestamp=xx&sm=x
```

### 请求方法
GET

### 参数说明

| 字段      | 类型   | 名称        | 说明                                     |
|----------|-------|------------|------------------------------------------|
| spid     | string | 接口账号     |                                          |
| pwd      | string | 加密后密码   | [接口说明3](/books/message-cn-api/page/4f6ff "接口说明")                           |
| das      | string | 手机号      | 需加国际区码如：0062                       |
| sm       | string | 发送内容     | 需转换为16进制码（计算字符长度以原文为准） [附录3](/books/message-cn-api/page/java16#3)    |
| timestamp | string | 当前Unix timestamp（秒） | 例： 1601028870                |
| senderid | string | 非必填      | 合作伙伴后启用字段                         |

### 响应
```json
{
  "code": 0,
  "msg": "Success",
  "data": {
    "msgid": "100123",
    "parts": 1  //当前短信计费条数,如对计费有疑问请及时联系我们
  }
}
```

### 状态码(code)说明
- 0    -- 提交成功
- 101 -- 必填字段不能空（注意请求方式为GET）
- 102 -- 验证失败（Unix timestamp不分时区，要验证时间，确保误差范围 [-10s, 10s]）
- 103 -- spid 不存在
- 104 -- 密码不匹配（参数必须包含timestamp）
- 105 -- 无可用通道(请联系管理员确认通道配置情况)
- 106 -- 配置错误
- 107 -- 手机已在黑名单
- 108 -- 内容超过最大字数
- 109 -- 解析失败，请确认接口参数
- 110 -- 请求IP限制
- 111 -- 该手机号发送限制（发送次数过多）
- 120 -- 系统错误，请稍后再试 （**重要提示1.1**）

# 多条短信发送

### 请求URL
```
https://{domain}/sms/rsend
```

### 请求方法
POST    Content-Type: application/x-www-form-urlencoded

### 参数说明

| 字段      | 类型   | 名称            | 说明                                   |
|----------|-------|----------------|----------------------------------------|
| spid     | string | 接口账号         |                                        |
| pwd      | string | 密码            |[接口说明3](/books/message-cn-api/page/4f6ff "接口说明") |
| timestamp | string | 当前Unix timestamp（秒） | 例： 1601028870                |
| dasm     | string | 发送内容（单次不超过 200个手机号） | 内容格式如下：<br>手机号,发送内容/手机号,发送内容 ... <br>[接口说明1，2](/books/message-cn-api/page/4f6ff "接口说明")    |
| senderid | string | 非必填          | 合作伙伴后启用字段                       |

### 响应
```json
{
  "code": 0,
  "msg": "Success",
  "data": [{
    "das": "00628131565746",
    "msgid": "100123",
    "parts": 1, //计算分条数
    "state": 0
  }]
}
```

### 状态码(code)说明
[附录1,2](/books/message-cn-api/page/java16#3)

# 短信回执状态查询（推送）

### 1 短信回执状态查询
#### 请求URL
```
https://{domain}/sms/state?spid=xx&pwd=xx&timestamp=xx&msgid=xx
```

#### 请求方法
GET

#### 参数说明

| 字段      | 类型   | 名称            | 说明                                |
|----------|-------|----------------|-------------------------------------|
| spid     | string | 接口账号        |                                     |
| pwd      | string | 密码           | [接口说明3](/books/message-cn-api/page/4f6ff "接口说明")                      |
| timestamp | string | 当前Unix timestamp（秒） | 例： 1601028870             |
| msgid    | string | 消息ID（单次不超过100个） | 查询多个回执可用逗号连接如:100123,100124 |

#### 响应
```json
{
  "code": 0,
  "msg": "Success",
  "data": [{
    "msgid": "100123",
    "state": 0
  }]
}
```

#### 回执状态说明
state  0-无回执(已提交通道)，1-回执成功，2-回执失败

### 2 短信回执状态推送

#### 接口说明
通道返回回执后，通过配置的url通知客户短信回执内容，如需要可将url告诉我们进行配置

#### 请求URL
```
http(s)://{your_callback_url}?msgid=36160109669&das=628131565746&state=1
```

#### 请求方法
GET

#### 参数说明
- msgid   消息ID
- state   0-无回执(已提交通道)，1-回执成功，2-回执失败

# 上报短信状态

### 接口说明
客户业务平台单位时间内(start_time~end_time)短信状态统计，便于监控及发现问题

### 请求URL
```
https://{domain}/sms/monitor
```

### 请求方法
POST    Content-Type: application/x-www-form-urlencoded

### 参数说明

| 字段      | 类型  | 名称                     | 说明                       |
|----------|------|-------------------------|----------------------------|
| spid     | string | 接口账号                 |                           |
| start_time | string | 开始时间 Unix timestamp（秒） | 数据统计开始时间, 例:1601028870 |
| end_time | string | 结束时间 Unix timestamp（秒） | 数据统计结束时间, 例:1601028870 |
| total    | int    | 提交记录总数              |                           |
| success  | int    | 成功状态数               |                           |

### 响应
```json
{
  "code": 0,
  "msg": "Success"
}
```

# 短信计费编码预检

本系统目前仅支持 GSM7 和 UCS2 两种短信字符编码，说明如下：

| 字符集    |  单条字符长度  | 长短信每条字符长度 | 说明 |
|----------|-------|----------------|----------------------------------------|
| GSM7     | 160 | 153        |适用由26个英文字母组成的语言，如英文，印尼语等|
| UCS2     | 70 | 67          |适用除GSM7外的语言，如西语，日语，汉语等|

__特别说明__

1. “^“，”~“，”\“, "{", "}", "\[", "\]", "|", "€"; 这些字符使用 GSM7 编码时占用两个字符长度
2. 对于HTTP接口，长短信按原文提交，不需要分条后提交
3. 为保证终端设备收到是整条长短信，系统需要使用UDH标识每条短信，因而：
   
   长短信每条长度 = 单条字符长度- UDH标识


### 短信内容编码检查接口

#### 接口说明
通过该接口可以检查当前内容使用的字符集 和计费条数

#### 请求URL
```
https://{domain}/sms/charset?spid=xx&pwd=xx&sm=xx&timestamp=xx
```

#### 请求方法
GET

#### 参数说明

| 字段      | 类型   | 名称        | 说明                                     |
|----------|-------|------------|------------------------------------------|
| spid     | string | 接口账号     |                                          |
| pwd      | string | 加密后密码   | [接口说明3](/books/message-cn-api/page/4f6ff "接口说明") |
| sm       | string | 送检内容     | 需转换为16进制码（Hex） [附录3](/books/message-cn-api/page/java16#3)   |
| timestamp | string | 当前Unix timestamp（秒） | 例： 1601028870                |

#### 响应
```json
{
    "code": 0,
    "msg": "Success",
    "data": {
        "charset": "UCS2"
        "detail": "Content billed as 2 messages. Charset: UCS2, 70 chars/msg.",
        "parts": 2, 
        "single": 70
    }
}
```

__问题排查:如果短信内容都是英文字母但是返回UCS2,建议删除所有空格再重新输入后重试，如还有问题请及时联系我们__

#### 响应字段说明

1. charset 当前内容使用字符集合，GSM7/UCS2
2. parts   当前内容计费条数
3. single  单条计费长度(含UDH)

# 附录

### 1. 状态码(code)说明
- 0    -- 提交成功
- 101 -- 必填字段不能空（注意请求方式为GET）
- 102 -- 验证失败（Unix timestamp不分时区，要验证时间，确保误差范围 [-10s, 10s]）
- 103 -- spid 不存在
- 104 -- 密码不匹配（参数必须包含timestamp）
- 105 -- 无可用通道(请联系管理员确认通道配置情况)
- 106 -- 配置错误
- 107 -- 手机已在黑名单
- 108 -- 内容超过最大字数
- 109 -- 扣费失败，请确定账户金额
- 110 -- 请求IP限制
- 111 -- 该手机号发送限制（发送次数过多）
- 120 -- 系统错误，请稍后再试 （**重要提示1.1**）

### 2. 单条短信状态码(state)说明
- 0    -- 提交成功
- 105 -- 无可用通道（请联系管理员确认通道配置情况）
- 106 -- 模版错误
- 107 -- 手机已在黑名单
- 108 -- 内容超过最大字符
- 109 -- 扣费失败，请确定账户金额
- 120 -- 系统错误，请稍后再试
- 130 -- 内容无法解析

### 3 字符转16进制（Hex）示例代码
<span id="hexsamplecode"></span>

#### 3.1 Java
```java
public static String strToHex(String str) {
    String st = "";
    try {
        byte[] by = str.getBytes("utf8");
        for (int i = 0; i < by.length; i++) {
            String strs = Integer.toHexString(by[i]);
            if (strs.length() > 2){
                strs = strs.substring(strs.length() - 2);
            } else if (strs.length() == 1) {
                //补足16进制 00~0F补足
                strs = String.format("%02x", by[i]);
            }
            st += strs;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return st;
}
```

#### 3.2 PHP
```php
bin2hex($utf8Str);
```

#### 3.2 Golang
```go
package main

import (
    "encoding/hex"
    "fmt"
)

func main() {
    // 转换字符串为字节切片
    byteData := []byte("测试数据")
    // 编码为十六进制字符串
    hexString := hex.EncodeToString(byteData)
    fmt.Println(hexString) // 输出十六进制表示
}

```