短信API·接口文档

接口说明 / 代码示例 / 错误代码定义 / 名词解释

、/cGFnZV9pZD0xODkwNCNiaXRfMnR点 蒂法可是大家发了开始的 ld2MiX接口说明 / 代码示例 Q==
短信API·接口文档

使用指南

发送须知 / 内容审核 /  开始发送 / 测试须知

、/cGFnZV9pZD0xODkwNCNiaXRfMnR点 蒂法可是大家发了开始的 ld2MiX接口说明 / 代码示例 Q==
接口说明 / 代码示例 / 错误代码定义 / 名词解释
 
 
注:JDK版本为 1.6
 
演示明码发送短信
package demo;
import java.net.URLEncoder;
import org.apache.http.client.fluent.Request;
/**
 * 
 */
public class SendDemo {
    public static void main(String[] args) throws Exception {
        
        // ====================================================================
        // 本例子只是用于演示,请不要在实际生产中使用
        // ====================================================================
        
        // 必须的验证参数
        String username = “用户名”;
        String password = “密码”;
        String url = “http://61.129.57.233:7891/mt”;
        
        // 短信相关的必须参数
        String mobile = “手机号码”;
        String message = “【蝶信】您的验证码为:1111,如果不是本人请忽略!”;
        
        // 装配GET所需的参数
        StringBuilder sb = new StringBuilder(2000);
        sb.append(url);
        sb.append(“?dc=15″); // 表明发送的是中文
        sb.append(“&sm=”).append( URLEncoder.encode(message, “utf8″) );
        sb.append(“&da=”).append( mobile );
        sb.append(“&un=”).append( username );
        sb.append(“&pw=”).append( password ); 
        sb.append(“&tf=3″); // 表示短信内容为 urlencode+utf8
        
        String request = sb.toString();
        System.out.println( request );
        
        // 以GET方式发起请求
        String result = Request.Get( request ).execute().returnContent().asString();
        
        System.out.println( result );
    }
}
 
使用签名方式来保护密码的发送方式
 
package demo;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.http.client.fluent.Request;

public class SendWithSign {
    
    /**
     * 计算签名(摘要)
     */
    public static String calculateSign(String username, String password, String timestamp, byte[] message) throws Exception {
        MessageDigest md = MessageDigest.getInstance(“MD5″);
        md.update( username.getBytes(“UTF8″) );
        md.update( password.getBytes(“UTF8″) );
        md.update( timestamp.getBytes(“UTF8″) );
        md.update( message );
        byte[] md5result = md.digest();
        return Base64.encodeBase64String( md5result );
    }
    
    public static void main(String[] args) throws Exception {
        
        // 必须的验证参数
        String username = “用户名”;
        String password = “密码”;
        String url = “http://61.129.57.233:7891/mt”;
        
        // 短信相关的必须参数
        String mobile = “手机号码”;
        String message = “【蝶信】您的验证码为:1111,如果不是本人请忽略!”;
        
        // 计算签名,注意这里的消息内容转字节时,编码对应dc=15
        byte[] messageBytes = message.getBytes(“GB18030″);
        SimpleDateFormat sdf = new SimpleDateFormat(“yyyyMMddHHmmss”);
        String timestamp = sdf.format(new java.util.Date() );
        String sign = calculateSign(username, password, timestamp, messageBytes);
        
        // 装配GET所需的参数
        StringBuilder sb = new StringBuilder(2000);
        sb.append( url );
        sb.append(“?dc=15″); // 表明发送的是中文dc=15
        sb.append(“&sm=”).append( Hex.encodeHexString( messageBytes ) ); // HEX方式
        sb.append(“&da=”).append( mobile );
        sb.append(“&un=”).append( username );
        sb.append(“&pw=”).append( URLEncoder.encode( sign, “utf8″) ); // 这里使用签名,不是密码
        sb.append(“&ts=”).append(timestamp); // 指示服务器使用签名(数字摘要)验证方式
        sb.append(“&tf=0″); // 表示短信内容为 HEX
        sb.append(“&rd=1″); // 需要状态报告
        
        String request = sb.toString();
        System.out.println( request );
        
        // 以GET方式发起请求
        String result = Request.Get( request ).execute().returnContent().asString();
        
        System.out.println( result );
    }
}
 
对请求到的上行信息和状态报告进行解析
解请求方式:http://61.129.57.233:7891/mo?un=用户名&pw=密码&rf=2
 
package demo;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.math.NumberUtils;
/**
 * HTTP方式接收状态报告的方式, 请部署到tomcat
 * 并对web.xml作适当配置
 */
public class ReceiveServlet extends HttpServlet {
    
    private static final long serialVersionUID = 0x1L;
    private byte[] decodeBytes(String s) {
        if ( s == null )
            return new byte[0];
        try {
            return Hex.decodeHex(s.toCharArray());
        } catch (DecoderException e) {
            throw new RuntimeException(e);
        }
    }
    
    private String decodeMessage(int dc, byte[] buf) {
        if ( buf == null )
            return “”;
        try {
            // 这里只解码了8
            if ( dc == 8 )
                return new String(buf, “UTF-16BE”);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new String(buf);
    }
    
    /**
     * 服务器通过GET方式向客户端投递状态报告和上行 
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // 输出请求信息
        System.out.println( req.getQueryString() );
        
        String op = req.getParameter(“op”);
        if ( “mo”.equals(op) ) {
            // 上行信息
            int dc = NumberUtils.toInt( req.getParameter(“dc”) );
            String mobile = req.getParameter(“sa”);
            String extendCode = req.getParameter(“da”);
            byte[] data = decodeBytes( req.getParameter(“sm”) );
            String message = decodeMessage(dc, data);
            // 业务处理
            onReceiveMO( extendCode, mobile, message );
        } else if ( “dr”.equals(op)) {
            // 状态报告
            String id = req.getParameter(“id”);
            String status = req.getParameter(“su”);
            int result = NumberUtils.toInt( req.getParameter(“rp”), 9 );
            // 业务处理
            onReceiveReport( id, result, status );
        } else {
            // 未定义,不会到达这里
        }
        resp.getWriter().write(“ok”);
    }
    
    private void onReceiveMO(String extendCode, String mobile, String message) {
        // 请迅速返回,一般是放入内存后直接返回
        System.out.println( “extendCode: ” + extendCode );
        System.out.println( “mobile: ” + mobile );
        System.out.println( “message: ” + message );
    }
    
    private void onReceiveReport(String id, int result, String status) {
        // 请迅速返回,一般是放入内存后直接返回
        System.out.println( “id: ” + id );
        System.out.println( “result: ” + result ); // 0 为成功,其他失败
        System.out.println( “status: ” +  status );
    }
    
}
 
相关jar包:
http://www.airlead.net/qfy-content/uploads/2017/05/0b0ee7cd0340ade2c2789cb4b884cd9a.zip
 
演示明码发送短信
注:提供给用户参考,请注意用户密码安全
 using System;
using System.Threading;
using System.Web;
using System.Text;
using System.Collections.Generic;


public class Hello
{
  public static void Main()
  {
  StringBuilder httpUrl=new StringBuilder();
  String url=”http://61.129.57.233:7891/mt”;
  String username=”用户名”;
  String password=”密码”;
  String mobile=”手机号码”;
  String message=”【蝶信】您好,您的验证码位:1100,如果不是本人请忽略”; \\短信内容,【蝶信】为前置签名必须拥有
  httpUrl.Append(url);
  httpUrl.Append(“?un=”).Append(username);
  httpUrl.Append(“&pw=”).Append(password);
  httpUrl.Append(“&da=”).Append(mobile);
  message = HttpUtility.UrlEncode(message, System.Text.Encoding.UTF8);
  httpUrl.Append(“&sm=”).Append(message);
  httpUrl.Append(“&tf=3&rd=1″);
  
  Console.WriteLine(httpUrl);
  
  
  } 
 
 
演示明码发送短信
注:提供给用户参考,请注意用户密码安全
<html>
<boday>
<?php
$username= “用户名”;
$password= “密码”;
$url= “http://61.129.57.233:7891/mt”;
$mobile= “手机号”;
$message= “【蝶信】您的验证码位:2000,请注意查收”; //发送内容  【蝶信】:签名 (必须存在)
$httpurl=$url.”?un=”.$username.”&pw=”.$password.”&da=”.$mobile.”&sm=”.urlencode($message).”&tf=3″;
print $httpurl;
?>
<a href=”<?php print $httpurl?>” >点击发送短信</a>
</body>
</html>
 
 
 
以下为系统定义的错误码列表
 
错误码 说明
9002 未知命令
9012 短信消息内容错误
9013 目标地址错误
9014 短信内容太长
9015 路由错误
9016 没有下发网关
9017 定时时间错误
9018 有效时间错误
9019 无法拆分或者拆分错误
9020 号码段错误
9021 消息编号错误,这个和 PacketIndex 参数有关
9022 用户不能发长短信(EsmClass 错误)
9023 ProtocolID 错误
9024 结构错误,一般是指长短信
9025 短信编码错误
9026 内容不是长短信
9027 签名不对
9028 目标网关不支持长短信
9029 路由拦截
9030 目标地址(手机号)太多
9031 目标地址(手机号)太少
9032 发送速度太快
9101 验证失败,一般和用户名/密码/IP 地址相关
9102 没有填写用户名
9103 名字没找到
9104 IP 地址不对
9105 超过最大连接数,就是 tcp 连接数, http 也是一样的
9106 协议版本错误
9107 帐号无效,比如过期/禁用
9902 网关无此能力
9903 二进制数据太长了;如网关没有特别说明,一般不能超过 140
9904 网关不支持 EsmClass 字段,或等同字段
9905 网关不支持 ProtocolID 字段,或等同字段
9906 网关不支持 UDHI 字段,或等同字段
9907 网关支持 Letter 字段发送, 但短信记录没有 letter
9908 网关不存在
9909 网关没有应答
9910 网关不支持该短信编码
9911 区域错误
9401 计费错误
9402 非法内容
9403 黑名单
9405 Api 帐号丢失
9406 配置拒绝,就是帐号设置了拒绝标记
9407 帐号没有生成时间,这个属于非法帐号
9408 消息超时,超过短信或帐号或系统设置的生存时间
9409 由约束规则拒绝
9410 状态报告超时
9412 帐号无效
9413 重发拦截
9414 转发时丢弃,比如该通道已经废弃
9415 人工审核失败
9416 可能是诈骗信息
9417 不匹配模板
9418 拒绝审核(审核功能可能关闭)
9419 超过该手机号码的日发送次数限制
9501 非法目标地址,即手机号
9502 消息无法投入队列
9601 上行路由失败
9602 超过最大重试
9701 通知失败
9702 处理配置错误
9801 投递地址错误
9802 无法连接到服务器
9803 投递发送数据失败
9804 投递接收结果失败
 
 
目前支持 GET 方法。 以下各参数未经说明不存在时,integer 作默认值 0 处理, string 则当作
null 处理。 一般 integer(1)等同 byte, integer(4) 等同 int, integer(8)等同 long
发送短信入口 http://<host>:<port>/mt
参数说明如下:
参数 类型 说明 参考
dc integer(1) 0 表示英文, 8 表示 UCS2, 15 表示中文

12.1

ec integer(1) 一般不用 12.2
sm string 默认 HEX 编码之消息内容;客户可以指定形式 12.3
pi integer(1) 一般不用 12.4
da string 手机号 12.5
sa string 扩展码,必须以账号设定的开头;可以不填写 12.6
ld string linkID,目前不用 12.7
ex integer(8) 外部编码, 长整型 12.8
rd integer(1) 是否需要状态报告 12.9
un string 用户名 12.10
pw string 密码 12.11
st string 定时发送时间; 可不填 12.12
mu string(32) 模块名,一般不用 12.13
pr integer(1) 优先级 12.14
vp string 有效期, 可不填 12.15
rf integer(1) 控制返回格式 12.16
ts string 时间标记,用于验证,格式 yyyyMMddHHmmss 12.26
tf integer(1) 短信内容的传输编码,默认为 0 表示 HEX 格式 12.28
 
颜色标出为必须填写
发送示例
,消息内容为ABC(414243 为十六进制表示),需要状态报告(rd=1):
http://61.129.57.233:7891/mt?un=star&pw=123456&da=13612345678&sm=414243&dc=15&rd=1
或者这样发送,内容为“ ABC”,设 置 tf=2需使用 URLEncoder
http://61.129.57.233:7891/mt?un=star&pw=123456&da=13612345678&sm=ABC&dc=15&tf=2
发送结果,字段含义如下:
参数 类型 说明 参考
r integer(4) 错误码,不存在时认为是 0,即没有错误。 12.17
id string 消息编号,成功时返回,失败时该字段可省略 12.18
发送结果返回举例:
当 rf=0 时,此为默认值,各字段以&分割
成功 id=<消息编号>
或者
r=0&id=<消息编号>
失败 r=<错误码>
当 rf=2 时,即 json 格式。 可能会出现未定义字段,忽略即可。缺失字段则按默认处理。
成功 {“id”:”<消息编号>”}
失败 {“r”:”9103″}
 
想发送中文,知道 UTF8 编码的,可以尝试使用 tf=3,dc=15 的设置。 具体解释请参考 tf 说明。
 
 
 
接收短信入口 http://<host>:<port>/mo
接收状态报告和上行信息都在该地址
参数 类型 说明 参考
un string 用户名 12.10
pw string 密码 12.11
fs integer(4) 返回大小设定 12.27
ts string 时间标记,用于验证,格式 yyyyMMddHHmmss 12.26
rf integer(1) 控制返回格式 12.16
tf integer(10) 短信内容的传输编码,默认为 0 表示 HEX 格式 12.28
 
应答消息以多行返回消息(”\r\n”分割)每行一个。 最后一个行分割可能不存在。
行间参数用
&分割
参数 类型 上行消息说明 状态报告说明 参考
op string momo dr 12.19
dc integer(1) 消息类型   12.1
pi integer(1) cmpp 之 tp_pid   12.4
ec integer(1) cmpp 之 tp_udhi   12.2
sa string 手机号   12.6
da string 扩展码   12.5
mu string 模块名   12.13
sm  string HEX 编码之消息内容   12.3
id string    消息编号 12.18
ex integer(8)   外部编码 12.8
su string   状态说明 12.20
sd  string 接收时间 提交时间 12.21
dd string   完成时间 12.22
rp integer(4)   错误码 12.23
bi integer(4)   拆分编号 12.24
di integer(4)   群发时号码的位置 12.25
 
 
除 op 之外,状态报告和 mo 的各个参数未必都存在,特别是兰色标出的。
客户也可根据需要申请主动推送之 http 接口,即由我方服务器向客户方服务器主动发送 http
请求, 每次一个数据; 参数如上说明,不再赘述。
这是推荐方式,可以保证上行和状态报告的及时性。

 
关于群发时装态报告返回的编号 id,一般为提交时返回的编号,客户可以以该 id 和手机号
为规则进行对应; 表中
<bi><di>分别和内容拆分和号码拆分有关, 如果存在都是从 开始。
如果账号设置了需要连续编号,则对于群发 
个号码,状态报告返回的编号为 id+0 
id+n-1。不建议群发。
接收上行和状态报告举例

http://61.129.57.233:7891/mo?un=star&pw=123456
如需返回 xml 格式的响应
http://61.129.57.233:7891/mo?un=star&pw=123456&rf=1
 
 

 
 

12.1. data_coding
消息编码,smpp data_coding8bits。 一般 0 表示英文,8 表示 unicode,15 表示中文。如果要
发送繁体、日文、韩文等文字,请使用
8,并将内容转为 UCS2(BigEndian)格式; 即每个字
符对应
2 个字节,高字节在前。

 
12.2. esm_class
smpp esm_class, 8bits;一般不用
 
12.3. content
默认 HEX 编码之消息内容;例如内容’ABC’HEX 后为’414243’;也可以指定编码格式。
详细请参考
transfer_encoding 的说明。
 
12.4. protocol_id
smpp protocol_id,cmpp tp_pid8bits;一般不用
 
12.5. dest_addr
在发送时为手机号码;多个号码用分号(半角)分割。 请不要超过 100
在接收上行信息时为扩展码,一般为数字字符串
 
12.6. source_addr
在发送时为扩展码,必须以账号设定的开头;可以不填写。
在接收上行信息时为手机号码
 
12.7. link_id
目前不用
 
12.8. external_id
外部编码,长整型;客户可以自行填写, 状态报告时返回
 
12.9. registered_delivery
是否需要状态报告; 0 表示不需要; 1 表示需要
 
12.10. username
用户名
 
12.11. password
密码。 请不要在通讯中直接使用密码,如必须使用,请务必提供 IP 地址进行锁定。
 
12.12. schedule_time
定时发送时间;格式 yyyyMMddHHmmss;可不填
 
12.13. module
模块名,一般不用填写

12.14. priority
优先级, 取值范围 0~1,一般不设;账号优先级由系统控制,并可以根据规则自行调整。
 
12.15. validity_period
有效期;格式 yyyyMMddHHmmss;可不填
 
12.16. response_format
控制返回格式:
0: 默认格式,即文本格式。
1xmlxml 格式中的元素名同 HTTP 接口命名。
2json 格式
 
12.17. result
错误码, 0 表示成功,其他错误代码;在 0 时该字段可省略
 
12.18. message_id
消息的唯一编号(如果是群发则相当于批号), 发送时返回;用于在状态报告接收时进行匹
配。
 
12.19. operation
取值 mo 或者 dr 表明这是一个上行短信或者状态报告

12.20. status
状态报告描述字符串
 
12.21. submit_date
消息提交时间
 
12.22. done_date
消息完成时间
 
12.23. receipt
状态报告错误码, 0 表示用户接收成功。
 
12.24. block_index
消息发生拆分,该值表明这是第几段消息
 
12.25. dest_index
在群发时该字段表示,第几个号码。如果群法时有些号码是非法的,则这些号码没有编号。
也就是说只给那些服务器接收并产生下发记录的消息编号。
 
12.26. timestamp
如果该字段存在,服务器将认为 password 由如下方式计算得出:
password=Base64(MD5(username+password+timestamp+content))
其中 usernamepasswordtimestamp utf-8 处理成字节数组。 拼接时是按字节数组拼接
(content 是按原始短信字节数组处理,并非编码后的字符串)MD5 之后得到 16 字节(非长
度为
32 的字符串),再使用 Base64 编码。 如果 content 不存在,则不参与计算
该字段格式
yyyyMMddHHmmss
java
的示例代码如下:
SimpleDateFormat sdf = new SimpleDateFormat(“yyyyMMddHHmmss”);
String timestamp = sdf.format(new Date() );
MessageDigest md5 = MessageDigest.getInstance(“MD5″);
md5.update( username.getBytes(“utf8″) );
md5.update( password.getBytes(“utf8″) );
md5.update( timestamp.getBytes(“utf8″) );
if (message != null)
md5.update( message.getBytes(“utf8″) );
password = Base64.encodeBase64String( md5.digest() );

12.27. fetch_size
可以一次提取的数量,这个数量不能超过服务器段的配置。 如果超过或者无效,将以服务器
端的配置为准。
 
12.28. transfer_encoding
短信内容的传输编码
0HEX 编码格式(这是默认编码)
1
Base64 编码格式
2URLEncode 编码( 即针对字节进行 URLEncode 编码)
3URLEncode+UTF8( 即原始文本用 UTF8 转字节后进行 URLEncode 编码)
举例如下:
  tf取值  英文消息:”abc” 中文消息:”您好”
HEX 0 或者不设置   616263    c4fabac3
Base64 1    YWJj    xPq6ww==
URLEncode 2    abc    %C4%FA%BA%C3
URLEncode+UTF8 3    abc    %E6%82%A8%E5%A5%BD

说明:在以上例子中,英文消息请设置 dc=0,中文消息设置 dc=15gbk)。
如果发送日文,韩文等其他特殊语言字符,请设置
dc=8,并使用 tf=3 的方式。