SMPP协议是Short Message Peer to Peer的简称,规范上将它是一个开放式的工业标准协议。它为消息中心和短消息系统
应用端在短信数据传输时提供灵活的数据通信接口规范。不知道大家看到这些介绍是什么感觉,我看到的感觉就是云山雾罩不知所云。
下面根据我的实际开发经验,上硬货。
我做的某运营商行业短信网关中,它与移动的短信网关接口走的是SMPP协议,它与电信的网关接口走的也是SMPP协议。当
运营商之间的短信网关互通时,也被称为“异网”互通,大都用的SMPP。如果运营商内部的短信网关互通时用的协议就互不相同了,
其中移动内部短信网关互通用的CMPP协议,联通内部短信网关互通用的是SGIP协议,电信内部短信网关互通用的是SGIP协议。
我做的短信网关与运营商的短信中心通过TCP/IP建立连接后,然后用用BIND信令和短信网关建立连接,采用deliver或submit发送短信。
总体消息交互图如下:
语法规则在以下语法说明中,遵从以下规则:
A.未使用的字段,依据类型必须设置为0或NULL。
B.消息由消息头和消息体组成
C.状态(status)如在命令语法中未加说明
0:表示成功
非0:表示失败
<0x80000000:未定义值保留
D.在类型中,可能用到以下定义
| 说明 |
YY' | 年份的最后2位 (00-99) |
MM | 月份(01-12) |
DD | 日 (01-31) |
Hh | 小时 (00-23) |
Mm | 分 (00-59) |
Ss | 秒 (00-59) |
T | 十分之一秒 (0-9) |
Nn | 与UTC (Universal Time Constant) 时间超前或落后的差距(00-48). |
‘+’(p) | 时间超前于UTC time. |
‘-’(p) | 时间落后于 UTC time. |
C_UnicodeString :Unicode编码的字符串。
字段 | 长度(字节) | 类型 |
Command Length | 4 | Integer |
Command ID | 4 | Integer |
Command_status | 4 | Integer |
Sequence No. | 4 | Integer |
Optional Message Body | 可变 | 混合 |
具体字段描述说明:
Command ID 编码 | Command ID | 描述 | Command ID取值 |
ESME_BNDRCV | bind_receiver | ESME要求以接收者身份连接到SMSC | 0X00000001 |
ESME_BNDRCV_RESP | bind_receiver_resp | bind_receiver的响应 | 0X80000001 |
ESME_BNDTRN | bind_transmitter | ESME要求以发送者身份连接到SMSC | 0X00000002 |
ESME_BNDTRN_RESP | bind_transmitrer_resp | bind_transmitter的响应 | 0X80000002 |
ESME_UBD | Unbind | ESME要求断开连接到SMSC | 0X00000006 |
ESME_UBD_RESP | Unbind_resp | Unbind的响应 | 0X80000006 |
ESME_SUB_SM | Submit_sm | ESME提交短消息到SMSC | 0X00000004 |
ESME_SUB_SM_RESP | Submit_sm_resp | submit_sm的响应 | 0X80000004 |
SMSC_DELIVER_SM | Deliver_sm | SMSC下发短消息到ESME | 0X00000005 |
SMSC_DELIVER_SM_RESP | Deliver_sm_resp | deliver_sm的响应 | 0X80000005 |
ESME_QRYLINK | Enquire_link | ESME询问与SMSC的连接情况 | 0X00000015 |
ESME_QRYLINK_RESP | Enquire_link_resp | enquire_link的响应 | 0X80000015 |
ESME_NACK | Nack | 表示消息头有错误的响应 | 0X80000000 |
Command Status取值说明 :
错误代码 | 错误值 | 描述 |
E_SUCCESS | 0X00000000 | 成功 |
E_OTHERERR | 0X00000001 | 其他错误 |
0X00000002 – 0X0000000F |
| 保留给SMSC厂商定义错误 |
E_MSGLENERR | 0X00000010 | 消息长度错误 |
E_CMDLENERR | 0X00000011 | 命令长度错误 |
E_INVLDCMDID | 0X00000012 | 消息ID无效 |
E_NORIGHT(0X00000013) | 0X00000013 | 没有执行此命令的权限 |
0X00000014 – 0X0000001F |
| 保留 |
E_INVLDSYSTEMID | 0X00000020 | 无效的SYSTEMID |
E_INVLDPASSWORD | 0X00000021 | 无效的密码 |
E_INVLDSYSTEMTYPE | 0X00000022 | 无效的SYSTEMTYPE |
0X00000023 – 0X0000003F |
| 保留 |
E_ADDRERR | 0X00000040 | 地址错误 |
E_MOEXCEED | 0X00000041 | 超过最大提交数 |
E_MTEXCEED | 0X00000042 | 超过最大下发数 |
E_INVLDUSER | 0X00000043 | 无效的用户 |
E_INVLDDATAFMT | 0X00000044 | 无效的数据格式 |
E_CREATEMSGFAILURE | 0X00000045 | 创建消息失败 |
E_INVLDMSGID | 0X00000046 | 无效的短消息ID |
E_DATABASEFAILURE | 0X00000047 | 数据库失败 |
E_CANCELMSGFAILURE | 0X00000048 | 取消消息失败 |
E_MSGSTATEERR | 0X00000049 | 短消息状态错误 |
E_REPLACEMSGFAILURE | 0X0000004A | 替换消息失败 |
E_INVLDRPLADDR | 0X0000004B | 替换消息源地址错误 |
0X0000004C – 0X0000005F |
| 保留 |
E_INVLDORGTON | 0X00000060 | 无效的源地址TON |
E_INVLDORGNPI | 0X00000061 | 无效的源地址NPI |
E_ORGADDRERR | 0X00000062 | 源地址错误 |
E_INVLDDESTTON | 0X00000063 | 无效的目的地址TON |
E_INVLDDESTNPI | 0X00000064 | 无效的目的地址NPI |
E_DESTADDRERR | 0X00000065 | 目的地址错误 |
E_INVLDSCHEDULE | 0X00000066 | 无效的定时时间 |
E_INVLDEXPIRE | 0X00000067 | 无效的超时时间 |
E_INVLDESM | 0X00000068 | 无效的ESM_CALSS |
E_INVLDUDLEN | 0X00000069 | 无效的UDLEN |
E_INVLDPRI | 0X0000006A | 无效的PRI |
E_INVLDRDF | 0X0000006B | 无效的Registered_delivery_flag |
E_INVLDRPF | 0X0000006C | 无效的Replace_if_present_flag |
0X0000006D – 0X0000007F |
| 保留 |
用户管理部分(可选) |
|
|
E_USERALREADYEXIST | 0X00000080 | 指定用户已经存在 |
E_CREATEUSERERR | 0X00000081 | 创建用户失败 |
E_USERIDERR | 0X00000082 | 用户ID错误 |
E_USERNOTEXIST | 0X00000083 | 指定用户不存在 |
0X00000084 – 0X0000008F |
| 保留 |
0X00000090 – 0X00000FFF |
| 保留给SMSC厂商定义错误 |
其他 |
| 保留 |
Sequence No .:此字段表示消息的序列号,它由ESME产生,它是消息和它的应答之间的对应标志,数值在01h到07FFFFFFFh间。对于每条请求消息,该字段的取值必须保证严格单调递增,当序列号值达到最大值时,返回继续从01h开始。
Optional Message Body:此字段表示短消息的消息体部分。
此命令用于当接收消息头有错误的时候的响应,该响应只能由收到请求方发出。该命令只有消息头,没有消息体。
在扩展短消息实体和短消息中心之间建立虚连接,接收SMSC转发的短消息。
字段 | 长度(字节) | 类型 |
System_id | 最大 16 | C_String |
Password | 最大 9 | C_String |
System_type | 最大 13 | C_String |
Interface_version | 1 | Integer |
Addr_ton | 1 | Integer |
Addr_npi | 1 | Integer |
Address_range | 最大 41 | C_DecString |
具体字段描述说明:
system_id :该字段是系统登录到短消息中心所用的接口号。
Password :该字段是系统登录到短消息中心所用的密码。
system_type :该字段标明登录的接口类型。
interface_version :该字段标明登录的接口版本号。
addr_ton :该字段指明编码类型。如不需要,可设为NULL。取值说明:
0 未知,当用户或网络不含关于编码方案的较早信息
1 国际号码,
2 国内号码
3 网络特殊号码
4 用户号码
5 字符数字
6 缩写号码
7 保留
addr_npi :该字段指明编码方案。如不需要,可设为NULL。取值说明:
0 未知
1 ISDN或电话号码编码方案(E164/E163),对于任意实体SC,MSC或MS,都有效
2 保留
3 数据编码方案(X121)
4 电报编码方案
5-7 保留
8 国内编码方案
9 私有编码方案
10 ERMES编码方案(ETSI DE/PS 3 01-3)
11-15 保留
address_range :该字段用来给短消息指明路由,和将状态报告转发给ESME。如不需要,可设置为NULL。
此命令用于对MI_BIND_RECEIVER响应。
字段 | 大小(字节) | 类型 |
System_id | 最大 16 | C_String |
具体参数说明:
system_id :该字段是系统登录到短消息中心所用的接口号。
在扩展短消息实体和短消息中心之间建立虚连接,扩展短消息实体能向SMSC提交短消息。此命令和BIND_RECEIVER的语法一样,只是在消息头里的Command_id为"bind_transmitter"。
此命令和BIND_RECEIVER_RESP的语法一样,只是在消息头里的Command_id为"bind_transmitter_resp"。
此命令用于断开ESME和SMSC之间的连接。此消息只有消息头,没有消息体。
此消息只有消息头,没有消息体。
此命令用于用于ESME提交短消息到SMSC,以便SMSC把此短消息发给特定ESME。
字段 | 长度(字节) | 类型 |
service_type | 最大6 | C_String |
source_addr_ton | 1 | Integer |
source_addr_npi | 1 | Integer |
source_addr | 最大21 | C_DecString |
dest_addr_ton | 1 | Integer |
dest_addr_npi | 1 | Integer |
destination_addr | 最大21 | C_DecString |
esm_class | 1 | Integer |
protocol ID | 1 | Integer |
priority_flag | 1 | Integer |
schedule_delivery_time | 最大 17 | C_StringTime |
validity_period | 最大 17 | C_StringTime |
registered_delivery_flag | 1 | Integer |
replace_if_present_flag | 1 | Integer |
data_coding | 1 | Integer |
sm_default_msg_id | 1 | Integer |
sm_length | 1 | Integer |
short_message | 最大160 | C_String |
具体参数说明:
service_type :保留字段,为将来扩展用。必须设为NULL。
source_addr_ton :源地址编码类型,如不需要,可设为NULL。
source_addr_npi :源地址编码方案,如不需要,可设为NULL。
source_addr :提交该短消息的SME的地址。是提交的短消息的
源地址。如不需要,可设为NULL。
dest_addr_ton :目的地址编码类型,如不需要,可设为NULL。
dest_addr_npi :目的地址编码方案,如不需要,可设为NULL。
destination_addr:短消息的目的地址。对于移动终止的短消息来说,
它就是目的手机的MSISDN。如不需要,可设置为
NULL。
esm_class :该字短为短消息类型。对submit_sm消息来说,
该字段必须为NULL;对deliver_sm消息来说,该
字段表示这条消息是状态报告。该字段的具体解
释请参考后面的消息体参数说明。但对于普通的
SUBMIT_SM命令,此字段设为0。
取值说明 :
此字段的说明如下:
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Flag | Reserved | UDHI | Reserved | Reserved | Reserved | Delivery Receipt | Reserved | Reserved |
其中:
UDHI:表示短消息内容是否有头结构。置位表示有。
Delivery Receipt:在DELIVER_SM协议中使用,表示此条消息是否是状态报告。
protocol ID :GSM协议类型。详细是解释请参考GSM03.40中的
9.2.3.9。
priority_flag :短消息的优先级。当设置了短消息为高优先级,
短消息中心会将该短消息移到同一目的地址的消
息队列的前端,优先进行发送。
取值说明 :
0:普通优先级(缺省值)
1:高优先级
>1:保留。
schedule_delivery_time:该字段表示计划下发该短消息的时间。
时间格式请参考前面定义的C_StringTime
的格式. 如不需要,可设置为NULL。
validity_period:该字段表示短消息的最后生存期限。时间格式请
参考前面定义的C_StringTime的格式.如不需要,
可设置为NULL。
registered_delivery_flag:该字段是注册短消息标志,它表示当
短消息到达最后的目的地后,是否需
要状态报告。
取值说明:
0:不需要
1:需要
>1:保留。
replace_if_present_flag:该字段表示替换短消息标志。即当提交
的短消息的源地址和目的地址相同时,
是否替换存在的短消息。
取值说明:
0:不替换
1:替换
>1:保留。
data_coding :该字段表示数据编码方案。
取值说明 :
0 缺省编码方案(7bit编码)
4 二进制编码方案(8bit编码)
8 UCS2编码方案(GB13000)
其他 保留
sm_default_msg_id:该字段表示预定义短消息ID。该ID是短消息中
心管理者建立的预定义短消息表的索引。不想
发送预定义短消息时,该字段应设为NULL。预
定义短消息ID值从0x01到0x64。详细说明请参
考SMPP Applications Guide [9] - Default
Short Message。
sm_length :要发送的短消息数据内容的字节长度。
short_message :该字段表示短消息数据内容。最大可到160字符。
只有sm_length中定义的字节长度可用。此字段的数据编码格式由data_coding决定。
字段 | 长度(字节) | 类型 |
Message_id | 最大9 | C_HexString |
具体参数说明:
Message_id :该字段表示短消息ID,由短消息中心产生,用于
以后查询及替换短消息用,或是表明状态报告所
对应的源消息。如果没有,该字段必须设为
NULL。
此命令由SMSC产生,SMSC通过此命令发送短消息到目的ESME,它也可用于发送DELIVERY RECEIPT消息。语法格式与SUBMIT_SM的语法消息体是相同的,只是在消息头中的Command_id是“deliver_sm"。
字段 | 长度(字节) | 类型 |
service_type | 最大6 | C_String |
source_addr_ton | 1 | Integer |
source_addr_npi | 1 | Integer |
source_addr | 最大21 | C_DecString |
dest_addr_ton | 1 | Integer |
dest_addr_npi | 1 | Integer |
destination_addr | 最大21 | C_DecString |
esm_class | 1 | Integer |
protocol ID | 1 | Integer |
priority_flag | 1 | Integer |
schedule_delivery_time | 最大 17 | C_StringTime |
validity_period | 最大 17 | C_StringTime |
registered_delivery_flag | 1 | Integer |
replace_if_present_flag | 1 | Integer |
data_coding | 1 | Integer |
sm_default_msg_id | 1 | Integer |
sm_length | 1 | Integer |
short_message | 最大160 | C_String |
具体参数说明:
service_type :保留字段,为将来扩展用。必须设为NULL。
source_addr_ton :源地址编码类型,如不需要,可设为NULL。
source_addr_npi :源地址编码方案,如不需要,可设为NULL。
source_addr :提交该短消息的SME的地址。是提交的短消息的
源地址。如不需要,可设为NULL。
dest_addr_ton :目的地址编码类型,如不需要,可设为NULL。
dest_addr_npi :目的地址编码方案,如不需要,可设为NULL。
destination_addr:短消息的目的地址。对于移动终止的短消息来说,
它就是目的手机的MSISDN。如不需要,可设置为
NULL。
esm_class :该字短为短消息类型。对submit_sm消息来说,
该字段必须为NULL;对deliver_sm消息来说,该
字段表示这条消息是状态报告。该字段的具体解
释请参考后面的消息体参数说明。但对于普通的
SUBMIT_SM命令,此字段设为0。
取值说明 :
此字段的说明如下:
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Flag | Reserved | UDHI | Reserved | Reserved | Reserved | Delivery Receipt | Reserved | Reserved |
其中:
UDHI:表示短消息内容是否有头结构。置位表示有。
Delivery Receipt:在DELIVER_SM协议中使用,表示此条消息是否是状态报告。
protocol ID :GSM协议类型。详细是解释请参考GSM03.40中的
9.2.3.9。
priority_flag :短消息的优先级。当设置了短消息为高优先级,
短消息中心会将该短消息移到同一目的地址的消
息队列的前端,优先进行发送。
取值说明 :
0:普通优先级(缺省值)
1:高优先级
>1:保留。
schedule_delivery_time:该字段表示计划下发该短消息的时间。
时间格式请参考前面定义的C_StringTime
的格式. 如不需要,可设置为NULL。
validity_period:该字段表示短消息的最后生存期限。时间格式请
参考前面定义的C_StringTime的格式.如不需要,
可设置为NULL。
registered_delivery_flag:该字段是注册短消息标志,它表示当
短消息到达最后的目的地后,是否需
要状态报告。
取值说明:
0:不需要
1:需要
>1:保留。
replace_if_present_flag:该字段表示替换短消息标志。即当提交
的短消息的源地址和目的地址相同时,
是否替换存在的短消息。
取值说明:
0:不替换
1:替换
>1:保留。
data_coding :该字段表示数据编码方案。
取值说明 :
0 缺省编码方案(7bit编码)
4 二进制编码方案(8bit编码)
8 UCS2编码方案(GB13000)
其他 保留
sm_default_msg_id:该字段表示预定义短消息ID。该ID是短消息中
心管理者建立的预定义短消息表的索引。不想
发送预定义短消息时,该字段应设为NULL。预
定义短消息ID值从0x01到0x64。详细说明请参
考SMPP Applications Guide [9] - Default
Short Message。
sm_length :要发送的短消息数据内容的字节长度。
short_message :该字段表示短消息数据内容。最大可到160字符。
只有sm_length中定义的字节长度可用。此字段的数据编码格式由data_coding决定。
它的语法和SUBMIT_SM_RESP的语法消息体是一样的,只是在消息头中的Command_id是“deliver_sm_resp"。
此命令用于ESME确认和SMSC之间的连接。ESME发送一条ENQUIRE_LINK命令,SMSC响应一条ENQUIRE_LINK_ACK命令,表示ESME和SMSC之间的连接正常。此命令只有消息头,没有消息体。
此命令只有消息头,没有消息体。
例如:
0:缺省编码方案(7位)
4:英文编码方案(不被手机支持)
8:UCS2编码方案(比如中文编码)
此字段的说明如下:
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Flag | Reserved | UDHI | Reserved | Reserved | Reserved | Delivery Receipt | Reserved | Reserved |
其中 UDHI 表示短消息内容是否有头结构。置位表示有。Delivery Receipt,在DELIVER_SM协议中使用,表示是否是此条消息是否是状态报告。
对于普通的SUBMIT_SM命令,此字段设为0。
例如: 1 表示ISDN电话编码计划
1:高优先级
0:普通优先级
>1:保留
0:不需要
1:需要
>1:保留
0:不替换
1:替换
>1:保留
0 未知号码
1 国际号码
2 国内号码
3 网络专用号码
4 用户号码
5 字母号码(按照 GSM TS03.38 7-bit 缺省字母表编码)
6 缩写号码
7 保留
validity_period:短消息的最后生存期限
当SMPP建链时,它有绑定的三种方式,分别如下:
Transmitter:顾名思义,这是用来发送短信的链路;但此发送短信需要辩证的看,一端是发送短信的,那么另外一端就是接收短信的。所以具体的应用场景要具体分析,不能说你的应用绑定了Transmitter的链路方式,就一定是发短信的,它也可以是指对端发短信,你的应用是来接收短信的。
Receiver:与Transmitter含义类同,它是用来接收短信的链路,但也要辩证的看。一端是接收短信,那么另外一端就是发送短信。你绑定的Receiver链路可以是接收短信,也可以是发送短信的。
Transreciver:顾名思义,这种绑定的方式既可以用来发短信也可以用来接收短信,收发都可用。这点上述的Transmitter和Receiver只能发或只能收不同。
初步进入SMPP开发的同学尤其要注意以上的差别。
硬货,如何发长短信,如何发闪信,如何发WAPPUSH短信。这三种短信除了经验非常丰富的开发者知道外,普通开发者是很难知晓开发方法的。
下面我将一一道来。
将Submit或Deliver消息中的esm_class设置为0X40,指示短信体内还有消息头。
然后短信体内增加6字节长度的长短信标识,分别是0x05,0x00,0x03和splitedRef,splitedMax,splitedSeq。
splitedRef是指短信的序列号1~255;splitedMax是指拆分长短信的条数,splitedSeq是指长短信的第几条。
后续会做一个长短信实例继续详细阐述。
SMPP发送闪信有两种方式,一种是设置可选参数,一种是设置文字的编码类型。
设置可选参数方式:
1201:1以及1204:0;其中1201参数是display_time,1204是ms_validity。规范上看设置这两个参数目前是对CDMA短信是好使的。但在移动测试时发现,GSM短信无法出现闪信效果,所以就引发了参数文字编码类型方式进行设置闪信。
文字编码类型:
如果短信采用UCS2编码,那么编码类型设置为0X18,下发的短信也可以出现闪信的效果。
发送WAPPUSH短信和长短信有些相似,它的esm_class设置为0X40,指示短信体内还有消息头。
然后将WAPPUSH短信的编码作为短信体嵌入到Submit或Deliver中就能实现了。