// Mobile SMS interface (CMPP 2.0)
//
Unit untyidonginterface;
Interface
Uses
Sysutils, untsocket, idglobal, messagedigest_5, types;
Const
{$ Region 'COMMAND _ id define '}
Cmpp_connect = $00000001; // request connection
Cmpp_connect_resp = $80000001; // request a connection response
Cmpp_terminate = $00000002; // terminate the connection
Cmpp_terminate_resp = $80000002; // terminate the connection response.
Cmpp_submit = $00000004; // submit the SMS
Cmpp_submit_resp = $80000004; // submit the SMS response
Cmpp_deliver = $00000005; // text message delivery
Cmpp_deliver_resp = $80000005; // send an SMS response
Cmpp_query = $00000006; // query the status of sent SMS messages
Cmpp_query_resp = $80000006; // send the SMS status query response
Cmpp_cancel = $00000007; // Delete SMS
Cmpp_cancel_resp = $80000007; // Delete the SMS response
Cmpp_active_test = $00000008; // activation test
Cmpp_active_test_resp = $80000008; // activate the Test Response
Cmpp_fwd = $00000009; // Forward Message
Cmpp_fwd_resp = $80000009; // forward to response
Cmpp_mt_route = $00000010; // Mt route request
Cmpp_mt_route_resp = $80000010; // Mt route request response
Cmpp_mo_route = $00000011; // Mo route request
Cmpp_mo_route_resp = $80000011; // Mo route request response
Cmpp_get_route = $00000012; // obtain a route request
Cmpp_get_route_resp = $80000012; // obtain the route request response
Cmpp_mt_route_update = $00000013; // Mt route update
Cmpp_mt_route_update_resp = $80000013; // Mt route update response
Cmpp_mo_route_update = $00000014; // Mo route update
Cmpp_mo_route_update_resp = $80000014; // Mo route update response
Cmpp_push_mt_route_update = $00000015; // Mt route update
Cmpp_push_mt_route_update_resp = $80000015; // Mt route update response
Cmpp_push_mo_route_update = $00000016; // Mo route update
Cmpp_push_mo_route_update_resp = $80000016; // Mo route update response
{$ Endregion}
Const_sp_id = 'hhjc'; // SP Enterprise Code
Const_shared_secret = ''; // pre-agreed between China Mobile and the source address entity
Const_version = 11; // the version number negotiated by both parties. (4-bit indicates the master version number, and 4-bit indicates the minor version number.
Type
{$ Region 'cache define '}
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 'public message header define '}
{
Total_length4unsigned integer total message length (including the message header and Message Body)
Command_id4unsigned integer command or response type
Sequence_id4unsigned integer indicates the serial number of the message, which is accumulated sequentially. The step is 1 and is used cyclically (the serial number of one request and one response message must be the same)
}
Tmsgheader = packed record
Total_length: Cardinal;
Command_id: Cardinal;
Sequence_id: Cardinal;
End;
{$ Endregion}
{$ Region 'SP request to connect to ismg (cmpp_connect) operation '}
{
Source_addr6octet string source address. sp_id is the enterprise code of SP.
Authenticatorsource16octet string is used to identify the source address. The value is calculated using one-way MD5 hash, which is expressed as follows:
Authenticatorsource =
MD5 (source_addr + 9 bytes 0 + Shared Secret + timestamp)
The Shared Secret is pre-agreed by China Mobile and the source address entity. The timestamp format is mmddhhmmss, which is a value of 10 characters, namely, month, day, hour, minute, and second.
Version1unsigned integer indicates the version number negotiated by both parties (4-bit indicates the master version number and 4-bit indicates the minor version number)
The plaintext of timestamp4unsigned integer timestamp, generated by the client in the format of mmddhhmmss, which is an integer of 10 digits and is right aligned.
}
Tconnect = packed record
Source_addr: tchar6;
Authenticatorsource: tchar16;
Version: byte;
Timestamp: Cardinal;
End;
Tconnectmsg = packed record
Head: tmsgheader;
Body: tconnect;
End;
{$ Endregion}
{$ Region 'SP submits an SMS (cmpp_submit) operation to ismg '}
{
Msg_id8unsigned integer ID, which is generated by the SP-side SMS gateway and left blank in this section.
Total number of messages with the same msg_id as pk_total1unsigned integer, starting from 1
Pk_number1unsigned INTEGER: Number of information with the same msg_id, starting from 1
Registered_delivery1unsigned integer whether the return status confirmation report is required:
0: No
1: Required
2: Generate SMC statement
(This type of SMS is only used by the gateway and is not sent to the destination terminal)
Msg_level1unsigned integer information level
Service_id10octet string business type. It is a combination of numbers, letters, and symbols.
Fee_usertype1unsigned integer billing user type field
0: msisdn billing for the destination terminal;
1: billing of the source terminal msisdn;
2: billing for SP;
3: This field is invalid. for billing information, see fee_terminal_id.
Fee_terminal_id21unsigned integer is the number of the paying user. (If this byte is left blank, this field is invalid. for billing information, see fee_usertype,
This field is mutually exclusive with the fee_usertype field)
Tp_pid1unsigned integergsm protocol type. For more information, see 9.2.3.9 in gsm03.40.
Tp_udhi1unsigned integergsm protocol type. For more information, see 9.2.3.23 in gsm03.40. use only one bit and align right.
Msg_fmt1unsigned integer Information Format
0: ASCII string
3: SMS card writing
4: binary information
8: ucs2 Encoding
15: including GB Chinese characters ......
Msg_src6octet string content source (sp_id)
Feetype2octet string tariff category
01: "billing user number" is free of charge
02: Information fee is calculated based on the "billing user number"
03: Information fee is collected on a monthly basis for the "billing user number"
04: cap the information fee for the "billing user number"
05: the "billing user number" is charged by SP.
Feecode6octet string fee code (in units)
Valid_time17octet string survival period. The format follows the smpp3.3 protocol.
At_time17octet string scheduled sending time. The format follows the smpp3.3 protocol.
Src_id21octet string source number
The SP service code or long number prefixed with the service code. The Gateway fills in the complete source_addr field of the smpp submit_sm message,
This number is eventually displayed as the caller number of the Short Message on the user's mobile phone.
Number of users that destusr_tl1unsigned integer receives information (less than 100 users)
Dest_terminal_id21 * destusr_tloctet string msisdn Number of the SMS recipient
Msg_length1unsigned integer length (when msg_fmt is set to 0: <160 bytes; other <= 140 bytes)
Msg_contentmsg_lengthoctet string Information Content
Reserve8octet string retained
}
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 sends SMS (cmpp_deliver) to SP operation '}
{
Msg_id8unsigned integer ID
Generate Algorithm As follows:
Use a 64-bit (8-byte) integer:
Time (in the format of mmddhhmmss, that is, month, day, minute, and second): bit64 ~ Bit39, where
Bit64 ~ Bit61: binary representation of a month;
Bit60 ~ Bit56: the binary representation of a day;
Bit55 ~ Bit51: binary representation of hours;
Bit50 ~ Bit45: binary representation of the minute;
Bit44 ~ Bit39: binary representation of seconds;
SMS gateway code: bit38 ~ Bit17: Convert the SMS gateway code to an integer and enter it in this field.
Serial number: bit16 ~ Bit1: The sequence is increased. The step size is 1 and is used cyclically.
If the parts cannot be filled, fill the left zero, and align the right.
Dest_id21octet string destination number
The service code of the SP, usually 4-6 bits, or a long number prefixed with the Service Code. This number is the called Number of the short message sent by the mobile phone user.
Service_id10octet string business type. It is a combination of numbers, letters, and symbols.
Tp_pid1unsigned integergsm protocol type. For more information, see 9.2.3.9 in gsm03.40.
Tp_udhi1unsigned integergsm protocol type. For more information, see 9.2.3.23 in gsm03.40. use only one bit and align right.
Msg_fmt1unsigned integer Information Format
0: ASCII string
3: SMS card writing
4: binary information
8: ucs2 Encoding
15: including GB Chinese Characters
Src_terminal_id21octet string source terminal msisdn number (enter the destination terminal number of the cmpp_submit message in the status report)
Registered_delivery1unsigned integer status report
0: non-State Report
1: status report
Msg_length1unsigned integer message length
Msg_contentmsg_lengthoctet string message content
Reserved8octet string reserved item
}
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 'Connection method '}
Function connect (sequence_id, timestamp: Cardinal;
Sp_id, authenticatorsource: ansistring; version: byte): Boolean; // connection
{
Source_addr6octet string source address. sp_id is the enterprise code of SP.
Authenticatorsource16octet string is used to identify the source address. The value is calculated using one-way MD5 hash, which is expressed as follows:
Authenticatorsource =
MD5 (source_addr + 9 bytes 0 + Shared Secret + timestamp)
The Shared Secret is pre-agreed by China Mobile and the source address entity. The timestamp format is mmddhhmmss, which is a value of 10 characters, namely, month, day, hour, minute, and second.
Version1unsigned integer indicates the version number negotiated by both parties (4-bit indicates the master version number and 4-bit indicates the minor version number)
The plaintext of timestamp4unsigned integer timestamp, generated by the client in the format of mmddhhmmss, which is an integer of 10 digits and is right aligned.
}
{$ Endregion}
{$ Region 'sending method '}
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_id8unsigned integer ID, which is generated by the SP-side SMS gateway and left blank in this section.
Total number of messages with the same msg_id as pk_total1unsigned integer, starting from 1
Pk_number1unsigned INTEGER: Number of information with the same msg_id, starting from 1
Registered_delivery1unsigned integer whether the return status confirmation report is required:
0: No
1: Required
2: Generate SMC statement
(This type of SMS is only used by the gateway and is not sent to the destination terminal)
Msg_level1unsigned integer information level
Service_id10octet string business type. It is a combination of numbers, letters, and symbols.
Fee_usertype1unsigned integer billing user type field
0: msisdn billing for the destination terminal;
1: billing of the source terminal msisdn;
2: billing for SP;
3: This field is invalid. for billing information, see fee_terminal_id.
Fee_terminal_id21unsigned integer is the number of the paying user (if this byte is left blank, this field is invalid. for billing information, see fee_usertype field. This field is mutually exclusive with fee_usertype field)
Tp_pid1unsigned integergsm protocol type. For more information, see 9.2.3.9 in gsm03.40.
Tp_udhi1unsigned integergsm protocol type. For more information, see 9.2.3.23 in gsm03.40. use only one bit and align right.
Msg_fmt1unsigned integer Information Format
0: ASCII string
3: SMS card writing
4: binary information
8: ucs2 Encoding
15: including GB Chinese characters ......
Msg_src6octet string content source (sp_id)
Feetype2octet string tariff category
01: "billing user number" is free of charge
02: Information fee is calculated based on the "billing user number"
03: Information fee is collected on a monthly basis for the "billing user number"
04: cap the information fee for the "billing user number"
05: the "billing user number" is charged by SP.
Feecode6octet string fee code (in units)
Valid_time17octet string survival period. The format follows the smpp3.3 protocol.
At_time17octet string scheduled sending time. The format follows the smpp3.3 protocol.
Src_id21octet string source number
The SP service code or long number prefixed with the service code. The Gateway fills in the complete source_addr field of the smpp submit_sm message, this number is eventually displayed as the caller number of the Short Message on the user's mobile phone.
Number of users that destusr_tl1unsigned integer receives information (less than 100 users)
Dest_terminal_id21 * destusr_tloctet string msisdn Number of the SMS recipient
Msg_length1unsigned integer length (when msg_fmt is set to 0: <160 bytes; other <= 140 bytes)
Msg_contentmsg_lengthoctet string Information Content
Reserve8octet string retained
}
{$ Endregion}
{$ Region 'receiving method '}
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_id8unsigned integer ID
The generation algorithm is as follows:
Use a 64-bit (8-byte) integer:
Time (in the format of mmddhhmmss, that is, month, day, minute, and second): bit64 ~ Bit39, where
Bit64 ~ Bit61: binary representation of a month;
Bit60 ~ Bit56: the binary representation of a day;
Bit55 ~ Bit51: binary representation of hours;
Bit50 ~ Bit45: binary representation of the minute;
Bit44 ~ Bit39: binary representation of seconds;
SMS gateway code: bit38 ~ Bit17: Convert the SMS gateway code to an integer and enter it in this field.
Serial number: bit16 ~ Bit1: The sequence is increased. The step size is 1 and is used cyclically.
If the parts cannot be filled, fill the left zero, and align the right.
Dest_id21octet string destination number
The service code of the SP, usually 4-6 bits, or a long number prefixed with the Service Code. This number is the called Number of the short message sent by the mobile phone user.
Service_id10octet string business type. It is a combination of numbers, letters, and symbols.
Tp_pid1unsigned integergsm protocol type. For more information, see 9.2.3.9 in gsm03.40.
Tp_udhi1unsigned integergsm protocol type. For more information, see 9.2.3.23 in gsm03.40. use only one bit and align right.
Msg_fmt1unsigned integer Information Format
0: ASCII string
3: SMS card writing
4: binary information
8: ucs2 Encoding
15: including GB Chinese Characters
Src_terminal_id21octet string source terminal msisdn number (enter the destination terminal number of the cmpp_submit message in the status report)
Registered_delivery1unsigned integer status report
0: non-State Report
1: status report
Msg_length1unsigned integer message length
Msg_contentmsg_lengthoctet string message content
Reserved8octet string reserved item
}
{$ Endregion}
{$ Region 'message serial number '}
VaR
G_sequence_id: Cardinal = 0;
Function getsequence_id: integer; // message serial number, which is accumulated sequentially. The step size is 1 and is used cyclically (the serial number of a request and a response message must be the same)
{$ Endregion}
Function MD5 (value: ansistring): string; // MD5 Encryption
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
// Initialization
Buf: = nil;
Fillchar (Head, sizeof (head ),'');
Fillchar (body, sizeof (body ),'');
Fillchar (MSG, sizeof (MSG ),'');
// Receive
If frmsocket. Connect then
Begin
Frmsocket. tcp. iohandler. readbytes (BUF, sizeof (MSG), false );
Bytestoraw (BUF, MSG, sizeof (MSG ));
Head: = msg. head;
Body: = MSG. Body;
// Resolution
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
// Initialization
Buf: = nil;
Fillchar (Head, sizeof (head ),'');
Fillchar (body, sizeof (body ),'');
Fillchar (MSG, sizeof (MSG ),'');
If frmsocket. Connect then
Begin
// Message Header
Head. total_length: = sizeof (head) + sizeof (body );
Head. command_id: = cmpp_submit;
Head. sequence_id: = sequence_id;
// Message Body
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 );
// Message
MSG. Head: = head;
MSG. Body: = body;
// Send
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
// Initialization
Buf: = nil;
Fillchar (Head, sizeof (head ),'');
Fillchar (body, sizeof (body ),'');
Fillchar (MSG, sizeof (MSG ),'');
Result: = frmsocket. Connect;
If result then
Begin
// Message Header
Head. total_length: = sizeof (tconnectmsg );
Head. command_id: = cmpp_connect;
Head. sequence_id: = sequence_id;
// Message Body
Strpcopy (body. source_addr, sp_id );
Strpcopy (body. authenticatorsource, authenticatorsource );
Body. Version: = version;
Body. timestamp: = timestamp;
// Message
MSG. Head: = head;
MSG. Body: = body;
// Send
Buf: = rawtobytes (MSG, sizeof (MSG ));
Frmsocket. tcp. iohandler. Write (BUF );
End;
End;
End.