// 移动短信接口(cmpp 2.0)
//

unit untYiDongInterface;

interface

uses
SysUtils, untSocket, IdGlobal, MessageDigest_5, Types;

const
{$REGION 'Command_Id定义'}
CMPP_CONNECT = $00000001; // 请求连接
CMPP_CONNECT_RESP = $80000001; // 请求连接应答
CMPP_TERMINATE = $00000002; // 终止连接
CMPP_TERMINATE_RESP = $80000002; // 终止连接应答
CMPP_SUBMIT = $00000004; // 提交短信
CMPP_SUBMIT_RESP = $80000004; // 提交短信应答
CMPP_DELIVER = $00000005; // 短信下发
CMPP_DELIVER_RESP = $80000005; // 下发短信应答
CMPP_QUERY = $00000006; // 发送短信状态查询
CMPP_QUERY_RESP = $80000006; // 发送短信状态查询应答
CMPP_CANCEL = $00000007; // 删除短信
CMPP_CANCEL_RESP = $80000007; // 删除短信应答
CMPP_ACTIVE_TEST = $00000008; // 激活测试
CMPP_ACTIVE_TEST_RESP = $80000008; // 激活测试应答
CMPP_FWD = $00000009; // 消息前转
CMPP_FWD_RESP = $80000009; // 消息前转应答
CMPP_MT_ROUTE = $00000010; // MT路由请求
CMPP_MT_ROUTE_RESP = $80000010; // MT路由请求应答
CMPP_MO_ROUTE = $00000011; // MO路由请求
CMPP_MO_ROUTE_RESP = $80000011; // MO路由请求应答
CMPP_GET_ROUTE = $00000012; // 获取路由请求
CMPP_GET_ROUTE_RESP = $80000012; // 获取路由请求应答
CMPP_MT_ROUTE_UPDATE = $00000013; // MT路由更新
CMPP_MT_ROUTE_UPDATE_RESP = $80000013; // MT路由更新应答
CMPP_MO_ROUTE_UPDATE = $00000014; // MO路由更新
CMPP_MO_ROUTE_UPDATE_RESP = $80000014; // MO路由更新应答
CMPP_PUSH_MT_ROUTE_UPDATE = $00000015; // MT路由更新
CMPP_PUSH_MT_ROUTE_UPDATE_RESP = $80000015; // MT路由更新应答
CMPP_PUSH_MO_ROUTE_UPDATE = $00000016; // MO路由更新
CMPP_PUSH_MO_ROUTE_UPDATE_RESP = $80000016; // MO路由更新应答
{$ENDREGION}
const_SP_Id = 'HHJC'; // SP的企业代码
const_shared_secret = ''; // 由中国移动与源地址实体事先商定
const_Version = 11; // 双方协商的版本号(高位4bit表示主版本号,低位4bit表示次版本号

type
{$REGION '缓存定义'}
TByte21 = array [0 .. 20] of Byte;
TByte8 = array [0 .. 7] of Byte;
TChar21 = array [0 .. 20] of AnsiChar;
TChar10 = array [0 .. 9] of AnsiChar;
TChar140 = array [0 .. 139] of AnsiChar;
TChar8 = array [0 .. 7] of AnsiChar;
TChar6 = array [0 .. 5] of AnsiChar;
TChar16 = array [0 .. 15] of AnsiChar;
TChar2 = array [0 .. 1] of AnsiChar;
TChar17 = array [0 .. 16] of AnsiChar;
{$ENDREGION}
{$REGION '公用消息头定义'}
{
Total_Length 4 Unsigned Integer 消息总长度(含消息头及消息体)
Command_Id 4 Unsigned Integer 命令或响应类型
Sequence_Id 4 Unsigned Integer 消息流水号,顺序累加,步长为1,循环使用(一对请求和应答消息的流水号必须相同)
}
TMsgHeader = packed record
Total_Length: Cardinal;
Command_Id: Cardinal;
Sequence_Id: Cardinal;
end;
{$ENDREGION}
{$REGION 'SP请求连接到ISMG(CMPP_CONNECT)操作'}
{
Source_Addr 6 Octet String 源地址,此处为SP_Id,即SP的企业代码。
AuthenticatorSource 16 Octet String 用于鉴别源地址。其值通过单向MD5 hash计算得出,表示如下:
AuthenticatorSource =
MD5(Source_Addr+9 字节的0 +shared secret+timestamp)
Shared secret 由中国移动与源地址实体事先商定,timestamp格式为:MMDDHHMMSS,即月日时分秒,10位。
Version 1 Unsigned Integer 双方协商的版本号(高位4bit表示主版本号,低位4bit表示次版本号)
Timestamp 4 Unsigned Integer 时间戳的明文,由客户端产生,格式为MMDDHHMMSS,即月日时分秒,10位数字的整型,右对齐 。
}
TConnect = packed record
Source_Addr: TChar6;
AuthenticatorSource: TChar16;
Version: Byte;
Timestamp: Cardinal;
end;

TConnectMsg = packed record
Head: TMsgHeader;
Body: TConnect;
end;
{$ENDREGION}
{$REGION 'SP向ISMG提交短信(CMPP_SUBMIT)操作'}
{
Msg_Id 8 Unsigned Integer 信息标识,由SP侧短信网关本身产生,本处填空。
Pk_total 1 Unsigned Integer 相同Msg_Id的信息总条数,从1开始
Pk_number 1 Unsigned Integer 相同Msg_Id的信息序号,从1开始
Registered_Delivery 1 Unsigned Integer 是否要求返回状态确认报告:
0:不需要
1:需要
2:产生SMC话单
(该类型短信仅供网关计费使用,不发送给目的终端)
Msg_level 1 Unsigned Integer 信息级别
Service_Id 10 Octet String 业务类型,是数字、字母和符号的组合。
Fee_UserType 1 Unsigned Integer 计费用户类型字段
0:对目的终端MSISDN计费;
1:对源终端MSISDN计费;
2:对SP计费;
3:表示本字段无效,对谁计费参见Fee_terminal_Id字段。
Fee_terminal_Id 21 Unsigned Integer 被计费用户的号码(如本字节填空,则表示本字段无效,对谁计费参见Fee_UserType字段,
本字段与Fee_UserType字段互斥)
TP_pId 1 Unsigned Integer GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.9
TP_udhi 1 Unsigned Integer GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.23,仅使用1位,右对齐
Msg_Fmt 1 Unsigned Integer 信息格式
0:ASCII串
3:短信写卡操作
4:二进制信息
8:UCS2编码
 15:含GB汉字 。。。。。。
Msg_src 6 Octet String 信息内容来源(SP_Id)
FeeType 2 Octet String 资费类别
01:对“计费用户号码”免费
02:对“计费用户号码”按条计信息费
03:对“计费用户号码”按包月收取信息费
04:对“计费用户号码”的信息费封顶
05:对“计费用户号码”的收费是由SP实现
FeeCode 6 Octet String 资费代码(以分为单位)
ValId_Time 17 Octet String 存活有效期,格式遵循SMPP3.3协议
At_Time 17 Octet String 定时发送时间,格式遵循SMPP3.3协议
Src_Id 21 Octet String 源号码
SP的服务代码或前缀为服务代码的长号码, 网关将该号码完整的填到SMPP协议Submit_SM消息相应的source_addr字段,
该号码最终在用户手机上显示为短消息的主叫号码
DestUsr_tl 1 Unsigned Integer 接收信息的用户数量(小于100个用户)
Dest_terminal_Id 21*DestUsr_tl Octet String 接收短信的MSISDN号码
Msg_Length 1 Unsigned Integer 信息长度(Msg_Fmt值为0时:<160个字节;其它<=140个字节)
Msg_Content Msg_length Octet String 信息内容
Reserve 8 Octet String 保留
}
TSubmit = packed record
Msg_Id: TByte8;
Pk_total: Byte;
Pk_number: Byte;
Registered_Delivery: Byte;
Msg_level: Byte;
Service_Id: TChar10;
Fee_UserType: Byte;
Fee_terminal_Id: TByte21;
TP_pId: Byte;
TP_udhi: Byte;
Msg_Fmt: Byte;
Msg_src: TChar6;
FeeType: TChar2;
FeeCode: TChar6;
ValId_Time: TChar17;
At_Time: TChar17;
Src_Id: TChar21;
DestUsr_tl: Byte;
Dest_terminal_Id: TByte21;
Msg_Length: Byte;
Msg_Content: TChar140;
Reserve: TChar8;
end;

TSubmitMsg = packed record
Head: TMsgHeader;
Body: TSubmit;
end;
{$ENDREGION}
{$REGION 'ISMG向SP送交短信(CMPP_DELIVER)操作'}
{
Msg_Id 8 Unsigned Integer 信息标识
生成算法如下:
采用64位(8字节)的整数:
时间(格式为MMDDHHMMSS,即月日时分秒):bit64~bit39,其中
bit64~bit61:月份的二进制表示;
bit60~bit56:日的二进制表示;
bit55~bit51:小时的二进制表示;
bit50~bit45:分的二进制表示;
bit44~bit39:秒的二进制表示;
短信网关代码:bit38~bit17,把短信网关的代码转换为整数填写到该字段中。
序列号:bit16~bit1,顺序增加,步长为1,循环使用。
各部分如不能填满,左补零,右对齐。
Dest_Id 21 Octet String 目的号码
SP的服务代码,一般4--6位,或者是前缀为服务代码的长号码;该号码是手机用户短消息的被叫号码。
Service_Id 10 Octet String 业务类型,是数字、字母和符号的组合。
TP_pid 1 Unsigned Integer GSM协议类型。详细解释请参考GSM03.40中的9.2.3.9
TP_udhi 1 Unsigned Integer GSM协议类型。详细解释请参考GSM03.40中的9.2.3.23,仅使用1位,右对齐
Msg_Fmt 1 Unsigned Integer 信息格式
0:ASCII串
3:短信写卡操作
4:二进制信息
8:UCS2编码
 15:含GB汉字
Src_terminal_Id 21 Octet String 源终端MSISDN号码(状态报告时填为CMPP_SUBMIT消息的目的终端号码)
Registered_Delivery 1 Unsigned Integer 是否为状态报告
0:非状态报告
1:状态报告
Msg_Length 1 Unsigned Integer 消息长度
Msg_Content Msg_length Octet String 消息内容
Reserved 8 Octet String 保留项
}
TDeliver = packed record
Msg_Id: TByte8;
Dest_Id: TChar21;
Service_Id: TChar10;
TP_pId: Byte;
TP_udhi: Byte;
Msg_Fmt: Byte;
Src_terminal_Id: TChar21;
Registered_Delivery: Byte;
Msg_Length: Byte;
Msg_Content: TChar140;
Reserved: TChar8;
end;

TDeliverMsg = packed record
Head: TMsgHeader;
Body: TDeliver;
end;
{$ENDREGION}
{$REGION '连接方法'}

function Connect(Sequence_Id, Timestamp: Cardinal;
SP_Id, AuthenticatorSource: AnsiString; Version: Byte): Boolean; // 连接
{
Source_Addr 6 Octet String 源地址,此处为SP_Id,即SP的企业代码。
AuthenticatorSource 16 Octet String 用于鉴别源地址。其值通过单向MD5 hash计算得出,表示如下:
AuthenticatorSource =
MD5(Source_Addr+9 字节的0 +shared secret+timestamp)
Shared secret 由中国移动与源地址实体事先商定,timestamp格式为:MMDDHHMMSS,即月日时分秒,10位。
Version 1 Unsigned Integer 双方协商的版本号(高位4bit表示主版本号,低位4bit表示次版本号)
Timestamp 4 Unsigned Integer 时间戳的明文,由客户端产生,格式为MMDDHHMMSS,即月日时分秒,10位数字的整型,右对齐 。
}
{$ENDREGION}
{$REGION '发送方法'}
procedure Send(Sequence_Id: Cardinal; Pk_total, Pk_number, Registered_Delivery,
Msg_level, Fee_UserType, TP_pId, TP_udhi, Msg_Fmt, DestUsr_tl,
Msg_Length: Byte; Service_Id, Msg_src, FeeType, FeeCode, ValId_Time, At_Time,
Src_Id, Msg_Content: AnsiString; Dest_terminal_Id: AnsiString);
{
Msg_Id 8 Unsigned Integer 信息标识,由SP侧短信网关本身产生,本处填空。
Pk_total 1 Unsigned Integer 相同Msg_Id的信息总条数,从1开始
Pk_number 1 Unsigned Integer 相同Msg_Id的信息序号,从1开始
Registered_Delivery 1 Unsigned Integer 是否要求返回状态确认报告:
0:不需要
1:需要
2:产生SMC话单
(该类型短信仅供网关计费使用,不发送给目的终端)
Msg_level 1 Unsigned Integer 信息级别
Service_Id 10 Octet String 业务类型,是数字、字母和符号的组合。
Fee_UserType 1 Unsigned Integer 计费用户类型字段
0:对目的终端MSISDN计费;
1:对源终端MSISDN计费;
2:对SP计费;
3:表示本字段无效,对谁计费参见Fee_terminal_Id字段。
Fee_terminal_Id 21 Unsigned Integer 被计费用户的号码(如本字节填空,则表示本字段无效,对谁计费参见Fee_UserType字段,本字段与Fee_UserType字段互斥)
TP_pId 1 Unsigned Integer GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.9
TP_udhi 1 Unsigned Integer GSM协议类型。详细是解释请参考GSM03.40中的9.2.3.23,仅使用1位,右对齐
Msg_Fmt 1 Unsigned Integer 信息格式
0:ASCII串
3:短信写卡操作
4:二进制信息
8:UCS2编码
 15:含GB汉字 。。。。。。
Msg_src 6 Octet String 信息内容来源(SP_Id)
FeeType 2 Octet String 资费类别
01:对“计费用户号码”免费
02:对“计费用户号码”按条计信息费
03:对“计费用户号码”按包月收取信息费
04:对“计费用户号码”的信息费封顶
05:对“计费用户号码”的收费是由SP实现
FeeCode 6 Octet String 资费代码(以分为单位)
ValId_Time 17 Octet String 存活有效期,格式遵循SMPP3.3协议
At_Time 17 Octet String 定时发送时间,格式遵循SMPP3.3协议
Src_Id 21 Octet String 源号码
SP的服务代码或前缀为服务代码的长号码, 网关将该号码完整的填到SMPP协议Submit_SM消息相应的source_addr字段,该号码最终在用户手机上显示为短消息的主叫号码
DestUsr_tl 1 Unsigned Integer 接收信息的用户数量(小于100个用户)
Dest_terminal_Id 21*DestUsr_tl Octet String 接收短信的MSISDN号码
Msg_Length 1 Unsigned Integer 信息长度(Msg_Fmt值为0时:<160个字节;其它<=140个字节)
Msg_Content Msg_length Octet String 信息内容
Reserve 8 Octet String 保留

}
{$ENDREGION}
{$REGION '接收方法'}
procedure Accept(var Msg_Id: AnsiString; var Dest_Id, Service_Id, Src_terminal_Id,
Msg_Content: AnsiString; var TP_pId, TP_udhi, Msg_Fmt, Registered_Delivery,
Msg_Length: Byte);
{
Msg_Id 8 Unsigned Integer 信息标识
生成算法如下:
采用64位(8字节)的整数:
时间(格式为MMDDHHMMSS,即月日时分秒):bit64~bit39,其中
bit64~bit61:月份的二进制表示;
bit60~bit56:日的二进制表示;
bit55~bit51:小时的二进制表示;
bit50~bit45:分的二进制表示;
bit44~bit39:秒的二进制表示;
短信网关代码:bit38~bit17,把短信网关的代码转换为整数填写到该字段中。
序列号:bit16~bit1,顺序增加,步长为1,循环使用。
各部分如不能填满,左补零,右对齐。
Dest_Id 21 Octet String 目的号码
SP的服务代码,一般4--6位,或者是前缀为服务代码的长号码;该号码是手机用户短消息的被叫号码。
Service_Id 10 Octet String 业务类型,是数字、字母和符号的组合。
TP_pid 1 Unsigned Integer GSM协议类型。详细解释请参考GSM03.40中的9.2.3.9
TP_udhi 1 Unsigned Integer GSM协议类型。详细解释请参考GSM03.40中的9.2.3.23,仅使用1位,右对齐
Msg_Fmt 1 Unsigned Integer 信息格式
0:ASCII串
3:短信写卡操作
4:二进制信息
8:UCS2编码
 15:含GB汉字
Src_terminal_Id 21 Octet String 源终端MSISDN号码(状态报告时填为CMPP_SUBMIT消息的目的终端号码)
Registered_Delivery 1 Unsigned Integer 是否为状态报告
0:非状态报告
1:状态报告
Msg_Length 1 Unsigned Integer 消息长度
Msg_Content Msg_length Octet String 消息内容
Reserved 8 Octet String 保留项
}
{$ENDREGION}

{$REGION '消息流水号'}
var
g_Sequence_Id: Cardinal = 0;
function GetSequence_Id: Integer; // 消息流水号,顺序累加,步长为1,循环使用(一对请求和应答消息的流水号必须相同)
{$ENDREGION}

function MD5(value: AnsiString): string; // MD5加密

implementation

function MD5(value: AnsiString): string;
var
m: IMD5;
begin
m := GetMD5;
m.Init;
m.Update(TByteDynArray(RawByteString(value)), Length(value));
Result := LowerCase(m.AsString);
end;

function GetSequence_Id: Integer;
begin
if g_Sequence_Id = 4294967295 then
g_Sequence_Id := 0;
g_Sequence_Id := g_Sequence_Id + 1;
Result := g_Sequence_Id;
end;

procedure Accept(var Msg_Id: AnsiString; var Dest_Id, Service_Id, Src_terminal_Id,
Msg_Content: AnsiString; var TP_pId, TP_udhi, Msg_Fmt, Registered_Delivery,
Msg_Length: Byte);
var
Head: TMsgHeader;
Body: TDeliver;
Msg: TDeliverMsg;
buf: TIdBytes;
begin
// 初始化
buf := nil;
FillChar(Head, SizeOf(Head), '');
FillChar(Body, SizeOf(Body), '');
FillChar(Msg, SizeOf(Msg), '');
// 接收
if frmSocket.Connect then
begin
frmSocket.tcp.IOHandler.ReadBytes(buf, SizeOf(Msg), false);
BytesToRaw(buf, Msg, SizeOf(Msg));
Head := Msg.Head;
Body := Msg.Body;
// 解析
if Head.Command_Id = CMPP_DELIVER then
begin
SetLength(Msg_Id, SizeOf(Body.Msg_Id) + 1);
Move(Body.Msg_Id, Msg_Id[1], SizeOf(Body.Msg_Id));
SetLength(Dest_Id, SizeOf(Body.Dest_Id) + 1);
Move(Body.Dest_Id, Dest_Id[1], SizeOf(Body.Dest_Id));
SetLength(Service_Id, SizeOf(Body.Service_Id) + 1);
Move(Body.Service_Id, Service_Id[1], SizeOf(Body.Service_Id));
TP_pId := Body.TP_pId;
TP_udhi := Body.TP_udhi;
Msg_Fmt := Body.Msg_Fmt;
SetLength(Src_terminal_Id, SizeOf(Body.Src_terminal_Id) + 1);
Move(Body.Src_terminal_Id, Src_terminal_Id[1], SizeOf(Body.Src_terminal_Id));
Registered_Delivery := Body.Registered_Delivery;
Msg_Length := Body.Msg_Length;
SetLength(Msg_Content, SizeOf(Body.Msg_Content) + 1);
Move(Body.Msg_Content, Msg_Content[1], SizeOf(Body.Msg_Content));
end;
end;
end;

procedure Send(Sequence_Id: Cardinal; Pk_total, Pk_number, Registered_Delivery,
Msg_level, Fee_UserType, TP_pId, TP_udhi, Msg_Fmt, DestUsr_tl,
Msg_Length: Byte; Service_Id, Msg_src, FeeType, FeeCode, ValId_Time, At_Time,
Src_Id, Msg_Content: AnsiString; Dest_terminal_Id: AnsiString);
var
Head: TMsgHeader;
Body: TSubmit;
Msg: TSubmitMsg;
buf: TIdBytes;
begin
// 初始化
buf := nil;
FillChar(Head, SizeOf(Head), '');
FillChar(Body, SizeOf(Body), '');
FillChar(Msg, SizeOf(Msg), '');
if frmSocket.Connect then
begin
// 消息头
Head.Total_Length := SizeOf(Head) + SizeOf(Body);
Head.Command_Id := CMPP_SUBMIT;
Head.Sequence_Id := Sequence_Id;
// 消息体
Body.Pk_total := Pk_total;
Body.Pk_number := Pk_number;
Body.Registered_Delivery := Registered_Delivery;
Body.Msg_level := Msg_level;
StrPCopy(Body.Service_Id, Service_Id);
Body.Fee_UserType := Fee_UserType;
Body.TP_pId := TP_pId;
Body.TP_udhi := TP_udhi;
Body.Msg_Fmt := Msg_Fmt;
StrPCopy(Body.Msg_src, Msg_src);
StrPCopy(Body.FeeType, FeeType);
StrPCopy(Body.FeeCode, FeeCode);
StrPCopy(Body.ValId_Time, ValId_Time);
StrPCopy(Body.At_Time, At_Time);
StrPCopy(Body.Src_Id, Src_Id);
Body.DestUsr_tl := DestUsr_tl;
Move(Dest_terminal_Id[1], Body.Dest_terminal_Id, Length(Dest_terminal_Id));
Body.Msg_Length := Msg_Length;
StrPCopy(Body.Msg_Content, Msg_Content);
// 消息
Msg.Head := Head;
Msg.Body := Body;
// 发送
buf := RawToBytes(Msg, SizeOf(Msg));
frmSocket.tcp.IOHandler.Write(buf);
end;
end;

function Connect(Sequence_Id, Timestamp: Cardinal;
SP_Id, AuthenticatorSource: AnsiString; Version: Byte): Boolean;
var
Head: TMsgHeader;
Body: TConnect;
Msg: TConnectMsg;
buf: TIdBytes;
begin
// 初始化
buf := nil;
FillChar(Head, SizeOf(Head), '');
FillChar(Body, SizeOf(Body), '');
FillChar(Msg, SizeOf(Msg), '');
Result := frmSocket.Connect;
if Result then
begin
// 消息头
Head.Total_Length := SizeOf(TConnectMsg);
Head.Command_Id := CMPP_CONNECT;
Head.Sequence_Id := Sequence_Id;
// 消息体
StrPCopy(Body.Source_Addr, SP_Id);
StrPCopy(Body.AuthenticatorSource, AuthenticatorSource);
Body.Version := Version;
Body.Timestamp := Timestamp;
// 消息
Msg.Head := Head;
Msg.Body := Body;
// 发送
buf := RawToBytes(Msg, SizeOf(Msg));
frmSocket.tcp.IOHandler.Write(buf);
end;
end;

end.

客户端调用示例:

function TSMSService.ConnectYDApp: Boolean; // 连接移动 应用层验证
var
  AuthenticatorISMG: AnsiString;
  SP_Id, SharedSecret, timestr: AnsiString;
  LengthI, i, Md5UpLen: Integer;
  str1: array [0 .. 30] of ansiChar;
  md5str: md5digest;
  md5_con: MD5Context;
  Version: Byte;
  Sequence_Id: Cardinal;
  bBool: Boolean;
  Status: Byte;
  AuthenticatorSource: TByte16;
  s:AnsiString;
  iTime: Cardinal;
  Msg: TConnectRespMsg;
  buf: TIdBytes;
begin
  try
    timestr := FormatDateTime('MMDDHHMMSS', now);
    SP_Id := '731145';
    SharedSecret :='888888';
   // Source_Addr+9 字节的0 +shared secret+timestamp
   // 6+9+9+10=34
    StrPCopy(str1, SP_Id + '000000000' + SharedSecret + timestr);
    for i := 6 to 14 do
      str1[i] := #0;
    MD5Init(md5_con);
    MD5Update(md5_con, str1, 31);
    MD5Final(md5_con, md5str);
    move(md5str, AuthenticatorSource, 16);

Sequence_Id := untYiDongInterface.GetSequence_Id;
    Version := $20;     // CMPP2.0
    untYiDongInterface.connect(Sequence_Id, StrToInt(timestr), SP_Id,AuthenticatorSource, Version);
    SMSService.CMPPTcp.IOHandler.ReadBytes(buf, SizeOf(Msg), False);
    BytesToRaw(buf, Msg, SizeOf(Msg));
    case Msg.Body.Status of
      0:
      begin
        OutputDebugView('CMPP 验证成功:SPID:'+SP_ID);
      end;
      1:
      begin
        OutputDebugView('CMPP 消息结构错误');
      end;
      2:
      begin
        OutputDebugView('CMPP 非法源地址');
      end;
      3:
      begin
        OutputDebugView('CMPP:认证错');
      end;
      4:
      begin
        OutputDebugView('CMPP:太高的版本');
      end;
    else
      OutputDebugView('CMPP 其他错误');
    end;
  except
    on e: Exception do
      OutputDebugView('ConnectYDApp 异常' + e.Message);
  end;
end;

移动CMPP2.0封装相关推荐

  1. 半桶水开发 CMPP2.0 with Spring + JPA 2

    [list] [*][url=http://rikugun.iteye.com/blog/296384]半桶水开发 CMPP2.0 with Spring + JPA 1[/url] [*][url= ...

  2. 协议开发 中移动CMPP2.0协议API(三)

    协议开发 中移动CMPP2.0协议API(三) 云网(jimzj@21cn.com) 接上篇... 五.发送接口 对于API来说,最重要的一部分就是去做发送数据了.通过SOCKET套接字与网关相连接后 ...

  3. SwiftUI3.0封装Lottie动画库

    SwiftUI3.0封装Lottie动画库 动画的json文件从阿里有个设计图片自己去下载,或者从github找 import SwiftUI import Lottie//SwiftUI 不能直接 ...

  4. 用C#做短信CMPP2.0/3.0协议 支持扩展号支持物理网卡

    此程序为中国移动CMPP协议程序接口,适合在中国移动申请了短信发送端口的公司使用. 短信群发已经成为现在软件系统.网络营销等必不可少的应用工具.可应用在短信验证.信息群发.游戏虚拟商品购买.事件提醒. ...

  5. cmpp2.0 php,174短信发送状态回执错误码、返回值信息、错误原因

    达信通为企业客户提供短信发送服务,适用于企业向客户发送验证码.通知.会员营销短信.验证码短信:向手机下发验证码,确认用户的真实性和安全性,如信息变更.安全登录:会员通知短信:支持各类业务场景的短信通知 ...

  6. cmpp2.0如何实现网关短信发送

    最近在工作中,遇到了客户需要根据移动公司的提供的网关来进行短信的开发,具体是根据CMPP2.0协议进行开发的,还是比较复杂,在网上找了很多程序,都不太好使,最后找了一个,然后根据具体情况进行了调整后, ...

  7. cmpp2.0 php,CMPP20ERR:短信发送状态回执错误码、返回值信息、错误原因

    达信通为企业客户提供消息发送服务,提供短信验证码.短信通知以及营销短信等多种服务,满足企业各种基础服务和运营活动需求.验证码短信:向手机下发验证码,确认用户的真实性和安全性,如用户登录.手机解绑:短信 ...

  8. 使用移动代理CMPP2.0,3.0协议实现短信发送-Java版,使用华为smproxy.jar包

    本文使用的是CMPP2.0,CMPP3.0和此逻辑类似,使用的Java类不同而已 1.配置文件 cmpp.xml <config><!--与InfoX建立连接所需参数-->&l ...

  9. Swift 3.0封装 URLSession 的GET/SET方法代替 Alamofire

    升级到 Swift3.0 之后,新版本的 Alamofire 只支持 iOS 9.0 以上的系统,如果要适配 iOS 8,需要自己封装 URLSession,下面是笔者的方案: 这里使用的是 Swif ...

  10. android rxbus2.0封装,浅谈Rxbus封装(一)

    最近再看一个项目,但是那个项目里面的Rxjava是1.x版本的,由于最近又有一个项目要开始了,在封装各种基类,所以我准备将项目中的Rxbus用Rxjava2.x来修改一下继续用,由于2.x的Rxjav ...

最新文章

  1. boost::units::base_dimension相关的测试程序
  2. 为什么Vue不能观察到数组length的变化?
  3. RabbitMQ六种队列模式-工作队列模式
  4. Linux下C语言开发(多任务编程之任务、进程、线程)
  5. 《计算机网络(第7版)》-谢希仁
  6. 图文介绍:Winhex的使用教程
  7. UE4 蓝图切换玩家控制
  8. 微信公众号卡券php开发,微信公众号实现会员卡领取功能
  9. FireFox火狐浏览器历史版本下载地址
  10. .NET 实现手机短信验证接口
  11. java基础-(六)-使用 Spring Initializr 创建springBoot项目
  12. 函数的定义、调用和声明
  13. SSLOJ 1459.空间简单度【扫描线】【线段树】
  14. oracle数据库数据备份
  15. 09高温假旅行——青烟蓬长大
  16. 联想拯救者笔记本安装Win10、Ubuntu16.04双系统
  17. QtQuick中设置代理上网及缓存-待续
  18. yy里怎么复制别人的话_怎么把复制的yy频道弄上去
  19. windows server 2019如何删除windows server backup备份的副本
  20. 前端综合项目-个人博客网页设计

热门文章

  1. 正在配置更新请勿关闭计算机怎么办,电脑开机“显示正在配置更新请勿关闭计算机”该怎么办?...
  2. 用USRP-LW N210搭建软件雷达系统
  3. catia中的螺旋伞齿轮画法_使用CATIA绘制斜齿轮(直齿轮)得画法教程.doc
  4. java hsqldb_Hsqldb入门
  5. hsqldb mysql 语法_hsqldb快速入门
  6. java 动态统计报表_java统计图表FineReport制作动态图表
  7. 基于SpringBoot的统计报表后台管理系统
  8. 如何选择物业管理软件,五大误区需要避免
  9. 网站地图(sitemap)在线生成
  10. Eucalyptus详解