⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 submitunit.pas

📁 联通短信平台,1,3版稳定版400条/s
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{*******************************************************************************
功能简述 : 中国联通短信发送端

其它说明 :  1. 参考中国联合通信公司短消息网关系统接口协议(SGIP1.3)
            2. 参考Short Message Peer-to-Peer Protocol Specification Version 5.0-Draft09
            3. GSM 03.38 version 7.2.0 Release 1998


********************************************************************************}

unit SubmitUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, ComCtrls, Buttons, DB, ADODB, IniFiles, ScktComp,
  DateUtils, MD5, WinSock, AppEvnts, SGIP12_Protocol;

type
  TMainForm = class(TForm)
    InfoMemo: TMemo;
    Panel1: TPanel;
    MainStatusBar: TStatusBar;
    Button_Start: TSpeedButton;
    Button_Shut: TSpeedButton;
    SpeedButton3: TSpeedButton;
    Panel_Line: TPanel;
    ADOConn: TADOConnection;
    SGIPSocket: TClientSocket;
    LoopTimer: TTimer;
    SpeedButton4: TSpeedButton;
    ApplicationEvents_X: TApplicationEvents;
    StoredProc: TADOStoredProc;
    procedure FormCreate(Sender: TObject);
    procedure SpStringToList(List: TStrings; const W: WideString; ICount: integer);
    procedure StrCopy(const Src: string; Dest: PChar; MaxSize: Integer);
    procedure WriteInfo(Str: string);
    procedure WriteActiveLog(SLines: string);
    function OpenSocket(): boolean;
    function GetBuf(Packet: TMemoryStream; ASavePath: string): string;
    procedure CloseSocket();
    function GetIniConfigFile(): string;
    function ConnectToDB(): boolean;
    function PackBadWord(Msg: string): string;
    procedure DelayTime();
    procedure LoadParameters();
    function UCS2toGB(P: Pointer; Size: Integer = 70): string;
    function UniCodeArrayToString(Content: PChar; Size: Integer): string;
    function ConvertMsgID(Msg_ID: PChar): string;
    function SGIP12_GetLSH(): LongWord;
    function SGIP12_CONNECT(): boolean;
    function SGIP12_TERMINATE(): boolean;
    function SGIP12_SUBMITEx(SubmitRecord: TSubmitRecord; var SequenceNumber1, SequenceNumber2, SequenceNumber3: integer): boolean;
    procedure SGIP12_SUBMITEx_BEGINWORK();
    procedure Button_StartClick(Sender: TObject);
    procedure Button_ShutClick(Sender: TObject);
    procedure SGIPSocketConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure SGIPSocketConnecting(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure SGIPSocketDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure SGIPSocketError(Sender: TObject; Socket: TCustomWinSocket;
      ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    procedure SpeedButton3Click(Sender: TObject);
    procedure InfoMemoChange(Sender: TObject);
    procedure ADOConnAfterConnect(Sender: TObject);
    procedure ADOConnAfterDisconnect(Sender: TObject);
    procedure ADOConnBeforeConnect(Sender: TObject);
    procedure ADOConnBeforeDisconnect(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure ApplicationEvents_XException(Sender: TObject; E: Exception);
    procedure LoopTimerTimer(Sender: TObject);
    procedure SpeedButton4Click(Sender: TObject);
  private
    { Private declarations }
    BadWordList: TStringList;
    F_Sequence_Number: LongWord;

    F_SPCode, F_SPCorpID, F_User, F_Passwd, F_NodId, F_BaseFetchFlag: string;
    F_DelayTime, F_MaxRecCount: Integer;
    F_ClearInfoLineCount, F_CanWriteLog, F_CanPackBadWord, F_SendCount, F_ErrorCount: integer;
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.SpStringToList(List: TStrings; const W: WideString; ICount: integer);
var
  V: string;
  P: PWideChar;
begin
  List.Clear;
  V := '';
  P := Pointer(W);
  while True do
  begin
    case P^ of
      #0: break;
    else
      V := V + P^;
      if Length(V) >= ICount then
      begin
        List.Add(V);
        V := '';
      end;
    end;
    Inc(P);
  end;
  if V <> '' then
    List.Add(V);
end;

procedure TMainForm.StrCopy(const Src: string; Dest: PChar; MaxSize: Integer);
var
  I, Len: Integer;
begin
  FillChar(Dest^, MaxSize, 0);
  Len := Length(Src) - 1;
  if Len > MaxSize then
    Len := MaxSize;
  for I := 0 to Len do
    Dest[I] := Src[I + 1];
end;

procedure TMainForm.WriteActiveLog(SLines: string);
var
  StrLogFile: string;
  tmpDate: TDateTime;
  TxtFile: TextFile;
begin
  tmpDate := Now;
  if not SysUtils.DirectoryExists(ExtractFilePath(Application.ExeName) + 'Log\') then
  begin
    Mkdir(PChar(ExtractFilePath(Application.ExeName) + 'Log\'));
  end;

  StrLogFile := IntToStr(YearOf(tmpDate)) + IntToStr(MonthOf(tmpDate)) + IntToStr(DayOf(tmpDate)) + '.S.txt';
  StrLogFile := ExtractFilePath(Application.ExeName) + 'Log\' + StrLogFile;

  AssignFile(TxtFile, StrLogFile);
  if FileExists(StrLogFile) then Append(TxtFile)
  else Rewrite(TxtFile);
  Writeln(TxtFile, SLines);
  CloseFile(TxtFile);
end;

procedure TMainForm.WriteInfo(Str: string);
var
  StrMKLine: string;
begin
  StrMKLine := 'SGIP1.3-> ' + format('%-20.20s', [DateTimeToStr(Now)]) + Str;
  self.InfoMemo.Lines.Add(StrMKLine);
  if F_CanWriteLog = 1 then
  begin
    self.WriteActiveLog(StrMKLine);
  end;
end;

function TMainForm.UniCodeArrayToString(Content: PChar; Size: Integer): string;
var
  R: PWord;
  P: PByteArray;
  W: WideString;
  Offset: Integer;
begin
  P := PByteArray(Content);
  Size := Size div 2;
  SetLength(W, Size);
  Offset := 0;
  R := PWord(W);
  while Size > 0 do
  begin
    R^ := P^[Offset] * 256 + P^[Offset + 1];
    Inc(R);
    Dec(Size);
    Inc(Offset, 2);
  end;
  Result := W;
end;


function TMainForm.UCS2toGB(P: Pointer; Size: Integer = 70): string;
var
  PP: PByte;
  I: Integer;
  ByteA: Byte;
  ByteB: Byte;
  P1: PByte;
  P2: PByte;
  Pw: PWideChar;
 //  s:string;
begin
  PP := PByte(P);
  I := 0;
  while (I < Size) do
  begin
    P1 := PP;
    ByteA := PP^;
    Inc(PP);
    P2 := PP;
    ByteB := PP^;
    Inc(PP);
    P1^ := ByteB;
    P2^ := ByteA;
    Inc(I);
  end;
  Pw := PWidechar(P);
  Result := Pw;
end;

function TMainForm.SGIP12_CONNECT(): boolean;
var
  StrTimeStamp: string;
  SGIPBind: TSGIPBind;
  SGIPBind_Resp: TSGIPBind_Resp;
  ScktStream: TWinSocketStream;
begin

  if not self.SGIPSocket.Active then
  begin
    Result := false;
    Exit;
  end;

  DateTimeToString(StrTimeStamp, 'mmddhhnnss', Now());
  FillChar(SGIPBind, SizeOf(SGIPBind), 0);
  FillChar(SGIPBind_Resp, SizeOf(SGIPBind_Resp), 0);
  with SGIPBind.Head do
  begin
    MessageLength := WinSock.htonl(SizeOf(SGIPBind));
    CommandId := WinSock.htonl(SGIP12_Protocol.SGIP_BIND);
    SNumber1 := WinSock.htonl(StrToInt64(self.F_NodId)); //
    SNumber2 := WinSock.htonl(StrToInt64(StrTimeStamp)); //
    SNumber3 := WinSock.htonl(self.SGIP12_GetLSH);
  end;

  with SGIPBind.Bind do
  begin
    LonginType := 1;
    StrPCopy(LonginName, self.F_User);
    StrPCopy(LonginPass, self.F_Passwd);
  end;

  try
    try
      ScktStream := TWinSocketStream.Create(self.SGIPSocket.Socket, 3000);
      ScktStream.Write(SGIPBind, SizeOf(SGIPBind));
      if ScktStream.WaitForData(5000) then
      begin
        ScktStream.Read(SGIPBind_Resp, sizeOf(SGIPBind_Resp));
        if SGIPBind_Resp.Bind_Resp.Result = 0 then
        begin
          self.WriteInfo('网关登陆成功.');
          Result := true;
        end else
        begin
          self.WriteInfo('网关登陆失败,错误代码为 ' + IntToStr(SGIPBind_Resp.Bind_Resp.Result) + ' ,可能原因为:' + SGIP12_Protocol.GetSGIP12ErrorInfo(SGIPBind_Resp.Bind_Resp.Result));
          Result := false;
        end;
      end else
      begin
        self.WriteInfo('网关登陆失败,指令发送等待超时,请查检网络状况.');
        Result := false;
      end;
    except
      on E: ESocketError do
      begin
        self.WriteInfo(E.Message);
        Result := false;
      end;
    end;
  finally
    FreeAndNil(ScktStream);
  end;
end;



function TMainForm.SGIP12_TERMINATE(): boolean;
var
  StrTimeStamp: string;
  SGIPUnBind: TSGIPUnBind;
  SGIPUnBind_Resp: TSGIPUnBind_Resp;
  ScktStream: TWinSocketStream;
begin

  Result := false;
  if not self.SGIPSocket.Active then
  begin
    Exit;
  end;

  DateTimeToString(StrTimeStamp, 'mmddhhnnss', Now());
  FillChar(SGIPUnBind, SizeOf(SGIPUnBind), 0);
  FillChar(SGIPUnBind_Resp, SizeOf(SGIPUnBind_Resp), 0);
  with SGIPUnBind.Head do
  begin
    MessageLength := WinSock.htonl(SizeOf(SGIPUnBind));
    CommandId := WinSock.htonl(SGIP12_Protocol.SGIP_UNBIND);
    SNumber1 := WinSock.htonl(StrToInt64(self.F_NodId)); //
    SNumber2 := WinSock.htonl(StrToInt64(StrTimeStamp)); //
    SNumber3 := WinSock.htonl(self.SGIP12_GetLSH);
  end;

  try
    try
      ScktStream := TWinSocketStream.Create(self.SGIPSocket.Socket, 3000);
      ScktStream.Write(SGIPUnBind, SizeOf(SGIPUnBind));
      if ScktStream.WaitForData(5000) then
      begin
        ScktStream.Read(SGIPUnBind_Resp, sizeOf(SGIPUnBind_Resp));
        self.WriteInfo('退出网关成功.');
        Result := true;
      end else
      begin
        self.WriteInfo('退出网关失败,指令发送等待超时,请查检网络状况.');
        Result := false;
      end;
    except
      on E: ESocketError do
      begin
        self.WriteInfo(E.Message);
        Result := false;
      end;
    end;
  finally
    FreeAndNil(ScktStream);
  end;
end;

function TMainForm.GetBuf(Packet: TMemoryStream; ASavePath: string): string;
var
  P: PByteArray;
  I: Integer;
  SL: TStringList;
begin
  Result := '';
  P := Packet.Memory;
  for I := 0 to Packet.Size - 1 do
    Result := Result + Format('%.2x ', [P^[I]]);

  if trim(ASavePath) <> '' then
  begin
    try
      SL := TStringList.Create;
      SL.Text := Result;
      SL.SaveToFile(ASavePath);
    finally
      FreeAndNil(SL);
    end;
  end;
end;

procedure TMainForm.SGIP12_SUBMITEx_BEGINWORK();
var
  QueryData: TADOQuery;
  upQueryData: TADOQuery;
  SubmitRecord: TSubmitRecord;
  SequenceNumber1, SequenceNumber2, SequenceNumber3: integer;
 // msgid: string;
begin
  if not self.ADOConn.Connected then Exit;
  try
    QueryData := TADOQuery.Create(self);
    QueryData.Connection := self.ADOConn;
    upQueryData := TADOQuery.Create(self);
    upQueryData.Connection := self.ADOConn;
    QueryData.Close; // 'SELECT *   FROM sms_submit where MOBILETYPE=2 and SENDSTATE=7  and rownum <=5 and (to_date(SCHEDULETIME,'+''''+'yyyy-mm-dd hh24:mi:ss'+''''+')<=sysdate or scheduletime is null ))'
    QueryData.SQL.Text := 'select * from SMS_SUBMIT where ((sendstate=7 and (to_date(SCHEDULETIME,' + '''' + 'yyyy-mm-dd hh24:mi:ss' + '''' + ')<=sysdate or scheduletime is null )) and mobiletype=2) and rownum <='+IntToStr(F_MaxRecCount) +'order by priority desc';
    QueryData.Open;
    if QueryData.RecordCount > 0 then
    begin
      if not self.SGIPSocket.Active then
      begin
        self.OpenSocket;
        self.SGIP12_CONNECT;
      end;
      //------------------------------Begin Submit------------------------------

      QueryData.First;
      while not QueryData.Eof do
      begin
        with SubmitRecord do
        begin
          F_RecordID := QueryData.FieldByName('SUBMITID').AsInteger; //SUBMITID           NUMBER(10) not null,
          F_SPNumber := QueryData.FieldByName('SPNumber').AsString; //SPNUMBER           Sp接入号
          F_ChargeNumber := QueryData.FieldByName('ChargeNumber').AsString; //CHARGENUMBER       计费号码
          F_UserNumber := QueryData.FieldByName('UserNumber').AsString; //USERNUMBER         接收用户手机号码
          F_ServiceType := trim(QueryData.FieldByName('ServiceType').AsString); //SERVICETYPE        业务代码
          F_FeeType := 1; //QueryData.FieldByName('FeeType').AsInteger; //FEETYPE            计费类型
          F_FeeValue := '0'; // QueryData.FieldByName('FeeValue').AsString; //FEEVALUE           短信费率
          F_GivenValue := QueryData.FieldByName('GivenValue').AsString; //GIVENVALUE         赠送用户的话费
          F_AgentFlag := 0; //QueryData.FieldByName('AgentFlag').AsInteger;             //
          F_MOrelatetoMTFlag := 0; //QueryData.FieldByName('MOTOMTFLAG').AsInteger;     //MOTOMTFLAG        引起MT消息的原因
          F_Priority := QueryData.FieldByName('Priority').AsInteger; //PRIORITY          优先级
          F_ExpireTime := QueryData.FieldByName('ExpireTime').AsString; //EXPIRETIME        存活有效期
          F_ScheduleTime := ''; //QueryData.FieldByName('ScheduleTime').AsString; //SCHEDULETIME      定时发送时间
          F_ReportFlag := 0; //QueryData.FieldByName('ReportFlag').AsInteger; //REPORTFLAG        是否需要返回状态报告
          F_TP_pid := 0; //QueryData.FieldByName('TP_pid').AsInteger;                    //
          F_TP_udhi := 0; // QueryData.FieldByName('TP_udhi').AsInteger;                  //
          F_MessageCoding := 15; //QueryData.FieldByName('MessageCoding').AsInteger;      //
          F_MessageType := 0; //QueryData.FieldByName('MessageType').AsInteger;          //
          F_LinkID := '0'; //QueryData.FieldByName('LinkID').AsString;                     //LINKID            点播业务使用的Link
          if F_CanPackBadWord = 1 then
          begin
            F_MessageContent := PackBadWord(QueryData.FieldByName('MESSAGE').AsString);
          end else
          begin
            F_MessageContent := QueryData.FieldByName('MESSAGE').AsString; //MESSAGE          短信内容
          end;

          if Length(F_UserNumber) = 11 then F_UserNumber := '86' + F_UserNumber;
          upQueryData.Close;
          upQueryData.SQL.Text := 'update  sms_submit set  SENDSTATE=1  ' + ' where submitid=' + inttostr(SubmitRecord.F_RecordID);
          upQueryData.ExecSQL;
        end;
        if self.SGIP12_SUBMITEx(SubmitRecord, SequenceNumber1, SequenceNumber2, SequenceNumber3) then
             QueryData.Delete

      else
    begin
      QueryData.Next;
    end;
    self.DelayTime;
  end;
      //------------------------------End Submit--------------------------------
  self.SGIP12_TERMINATE;
  self.CloseSocket;
end;
QueryData.Close;
finally
  FreeAndNil(upQueryData);
  FreeAndNil(QueryData);
end;
end;

function TMainForm.SGIP12_SUBMITEx(SubmitRecord: TSubmitRecord; var SequenceNumber1, SequenceNumber2, SequenceNumber3: integer): boolean;
var
  StrTimeStamp: string;
  SGIPSubmit: TSGIPSubmit;
  SGIPSubmit_Resp: TSGIPSubmit_Resp;
  ScktStream: TWinSocketStream;
  QueryError: TADOQuery;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -