• 移动CMPP2.0封装


    // 移动短信接口(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;

  • 相关阅读:
    小程序本地数据的存储
    cocos2d-x中CCTableView介绍
    C++中map容器的说明和使用技巧
    不修改代码,关闭vs2010 C4819警告
    Cocos2d-x 处理双击事件的两种方法
    Cocos2d-x 实现模态对话框
    Cocos2d-x init() 和 onEnter() 区别
    Cocos2d-x 中 CCProgressTimer
    Cocos2d-x 实现技能冷却效果
    输出第 n 个斐波纳契数(Fibonacci)
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/2772113.html
Copyright © 2020-2023  润新知