打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
delphi 短信

delphi 短信

时间:2011-5-26来源:yang 作者: peng点击: 9次

 //传输文件的服务器端
//这个程序在服务器端要一直开着,否则客户端连接不了服务器
//客户--->左右软件--->巨澜短信网关

unit uServer;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, IdBaseComponent, IdComponent, IdTCPServer,
  ComCtrls,uImpTxt, DB,ADODB,IniFiles;

type
//********************************************************************

    //自定义类型
    THandle = Integer;
    JL_HANDLE = Integer;
    PJL_HANDLE = ^JL_HANDLE;

    //以HTTP方式登陆返回操作句柄,当调用退出登陆时,此句柄自动失效。// 参数说明
    T_JL_TCPLogin = function(strHost: Pchar; // strHost:    主机名称或者IP地址: ‘http://www.surge.com.cn/ 不用改变
        nPort: Integer; // nPort:    端口号 : 6688 不用改变
        strUserId: Pchar; // strUserId:  用户名
        strPassword: Pchar; // strPassword:  用户密码
        nType: Integer; // nType连接类型,为 1 表示只发送, 为 2表示即可发送也可接收 默认为 2
        pRtnHandle: PJL_HANDLE): Integer stdcall; // pRtnHandle: 返回操作句柄

    //退出登陆,此句柄自动失效
    T_JL_Logout = function(pHandle: JL_HANDLE): Integer stdcall; // pRtnHandle: 登陆时的操作句柄

    //群发短信息
    T_JL_SendMsg = function(pHandle: JL_HANDLE; //操作句柄
        strFromPhone: Pchar; // strFromPhone  短消息发送者手机号码
        strToPhone: Pchar; // strToPhone  目的手机号码,如果有多个号码,用逗号进行分割,如13900000000, 13911111111, ...
        strContent: Pchar; // strContent  信息内容,信息长度不超过140字节,否则将返回 JL_ERR_CONTENT
        strSendTime: Pchar): Integer stdcall; // strSendTime  定时发送时间。格式:yyyy-mm-dd hh:mm:ss 为空时,表示立即发送

    //单发短信息
    T_JL_SingleSendMsg = function(pHandle: JL_HANDLE; //操作句柄
        strSerNo: PChar;      //自定义编号-以对应相应的状态报告
        strFromPhone: Pchar; // strFromPhone  短消息发送者手机号码
        strToPhone: Pchar; // strToPhone  目的手机号码,如果有多个号码,用逗号进行分割,如13900000000, 13911111111, ...
        strContent: Pchar; // strContent  信息内容,信息长度不超过140字节,否则将返回 JL_ERR_CONTENT
        strSendTime: Pchar): Integer stdcall; // strSendTime  定时发送时间。格式:yyyy-mm-dd hh:mm:ss 为空时,表示立即发送

   //查询帐户余额 -参数:fBalance:返回金额,单位为元
    T_JL_GetAccountBalance = function(pHandle: JL_HANDLE; fBalance: PSingle): Integer stdcall;

    // 查询单价 -参数:fPrice:返回金额,单位为元
    T_JL_GetAccountPrice = function(Handle: JL_HANDLE; fPrice: PSingle): Integer stdcall;

     // 修改用户密码
    T_JL_ModifyPassword = function(pHandle: JL_HANDLE; // 操作句柄
        strNewPassword: Pchar): Integer stdcall; //strNewPassword:新的密码

    // 接收短信返回的状态报告 pstrPhone [21] pstrDescribe[255]
    T_JL_GetOneReport = function(pHandle: JL_HANDLE; // 操作句柄
        pstrSerNo: PChar;   //用户自定义序列(单发时用户传过去的参数)
        pnReqID: PInteger; //返回MO短信ID
        pstrPhone: Pchar; //字符串缓冲区,大小至少为21字节,返回接收手机号码
        pnStatus: PInteger; // 返回短信息接收状态 0:发送失败 1:信息已发送到网关 3:信息已发送到手机
        pstrDescribe: Pchar): Integer stdcall; //字符串缓冲区,大小至少为256字节,返回状态描述

    T_JL_GetOneSM = function(pHandle: JL_HANDLE; // 操作句柄
        pnMsgID: PInteger; //信息id
        strFrom: Pchar; //返回发送者的手机号码 字符串缓冲区,大小至少为21字节
        strCreateTime: Pchar; // 返回发送时间 字符串缓冲区,大小至少为20字节
        strContent: Pchar): Integer stdcall; //返回消息内容 字符串缓冲区,大小至少为256字节。

    T_JL_GetOneSM_Ex = function(pHandle: JL_HANDLE; // 操作句柄
        pnMsgID: PInteger; //信息id
        strFrom: Pchar; //返回发送者的手机号码 字符串缓冲区,大小至少为21字节
        strTo:   Pchar; //字符串缓冲区,大小至少为21字节,返回来源端口号
        strCreateTime: Pchar; // 返回发送时间 字符串缓冲区,大小至少为20字节
        strContent: Pchar): Integer stdcall; //返回消息内容 字符串缓冲区,大小至少为256字节。

//********************************************************************
type
  TFormServer = class(TForm)
    IdTCPServer1: TIdTCPServer;
    BtnStart: TButton;
    StatusBar1: TStatusBar;
    BtnStop: TButton;
    LabeledEdit1: TLabeledEdit;
    ListBox1: TListBox;
    ADOQuery1: TADOQuery;
    ADOQuery2: TADOQuery;
    ADOConnection1: TADOConnection;
    ADOQuery3: TADOQuery;
    ADOQuery4: TADOQuery;
    procedure IdTCPServer1Execute(AThread: TIdPeerThread);
    procedure BtnStartClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure BtnStopClick(Sender: TObject);
    procedure IdTCPServer1Connect(AThread: TIdPeerThread);
    procedure ShowResultMsg(num: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
    OneHandle: THandle; //定义一个句柄变量
    pRtnHandle: JL_HANDLE; //定义一个句柄变量
    JL_TCPLogin: T_JL_TCPLogin; //登陆
    JL_Logout: T_JL_Logout; //退出
    JL_GetAccountPrice: T_JL_GetAccountPrice; //单价/条
    JL_GetAccountBalance: T_JL_GetAccountBalance; //帐户余额
    JL_ModifyPassword: T_JL_ModifyPassword; //修改密码
    JL_GetOneSM: T_JL_GetOneSM; //收取回复信息(HTTP)
    JL_GetOneSM_Ex: T_JL_GetOneSM_Ex; //收取回复信息(TCP)
    JL_GetOneReport: T_JL_GetOneReport; //收取状态报告
    JL_SingleSendMsg: T_JL_SingleSendMsg;  //单发信息
    JL_SendMsg: T_JL_SendMsg; // 群发信息
  end;

var
  FormServer: TFormServer;

const
  FFileName=‘d:\sms.txt‘;  //参数有待放进INI文件中
  FPort=9925;
  FUserName=‘‘;   //登录巨澜短信网关用户名和密码
  FPWS=‘‘;

implementation

uses uCommFunc;

{$R *.dfm}

//------返回错误列表--------------------------------------------------
procedure tformserver.ShowResultMsg(num: Integer);
begin
    case num of
        0: MessageBox(Handle, ‘正常!‘, ‘Surge‘, MB_ICONASTERISK);
        -1: MessageBox(Handle, ‘EPID错误‘, ‘Surge‘, MB_ICONHAND);
        -2: MessageBox(Handle, ‘无该用户‘, ‘Surge‘, MB_ICONHAND);
        -3: MessageBox(Handle, ‘注册码错‘, ‘Surge‘, MB_ICONHAND);
        -4: MessageBox(Handle, ‘用户被停用‘, ‘Surge‘, MB_ICONHAND);
        -5: MessageBox(Handle, ‘未注册成功‘, ‘Surge‘, MB_ICONHAND);
        -6: MessageBox(Handle, ‘超出使用日期‘, ‘Surge‘, MB_ICONHAND);
        -7: MessageBox(Handle, ‘费用不足‘, ‘Surge‘, MB_ICONHAND);
        -8: MessageBox(Handle, ‘源手机错误‘, ‘Surge‘, MB_ICONHAND);
        -9: MessageBox(Handle, ‘目的手机错误‘, ‘Surge‘, MB_ICONHAND);
        -10: MessageBox(Handle, ‘信息内容错误‘, ‘Surge‘, MB_ICONHAND);
        -11: MessageBox(Handle, ‘连接失败‘, ‘Surge‘, MB_ICONHAND);
        -12: MessageBox(Handle, ‘系统内部错误或者无效的客户状态‘, ‘Surge‘, MB_ICONHAND);
        -13: MessageBox(Handle, ‘客户权限不对‘, ‘Surge‘, MB_ICONHAND);
        -14: MessageBox(Handle, ‘不是从指定的IP处登录‘, ‘Surge‘, MB_ICONHAND);
        -15: MessageBox(Handle, ‘账号已经登录(TCP)‘, ‘Surge‘, MB_ICONHAND);
        -16: MessageBox(Handle, ‘内部通讯错误‘, ‘Surge‘, MB_ICONHAND);
        -17: MessageBox(Handle, ‘无可用的MT通道‘, ‘Surge‘, MB_ICONHAND);
        -18: MessageBox(Handle, ‘不支持该功能‘, ‘Surge‘, MB_ICONHAND);
        -19: MessageBox(Handle, ‘未定义错误‘, ‘Surge‘, MB_ICONHAND); //-------------未定义错误
        -20: MessageBox(Handle, ‘未知错误‘, ‘Surge‘, MB_ICONHAND);
        -21: MessageBox(Handle, ‘请求过于频繁‘, ‘Surge‘, MB_ICONHAND);
        -22: MessageBox(Handle, ‘信息内容有非法关键字‘, ‘Surge‘, MB_ICONHAND);
        -23: MessageBox(Handle, ‘错误的产品ID‘, ‘Surge‘, MB_ICONHAND);
        -24: MessageBox(Handle, ‘发送失败-Agent 断线‘, ‘Surge‘, MB_ICONHAND);
        -25: MessageBox(Handle, ‘发送失败-SMSC 断线‘, ‘Surge‘, MB_ICONHAND);
        -26: MessageBox(Handle, ‘发送失败-Agent 与 SMSC 之间断线‘, ‘Surge‘, MB_ICONHAND);
        -27: MessageBox(Handle, ‘错误的指令或格式‘, ‘Surge‘, MB_ICONHAND);
    else
        MessageBox(Handle, ‘未知错误‘, ‘Surge‘, MB_ICONHAND);
    end;
end;

procedure TFormServer.IdTCPServer1Execute(AThread: TIdPeerThread);
//const
//  c_sql=‘select * from sms_msg_server ‘+   //status:0/1/2 待发/成功/失败
//          ‘ where status=0 or status=2 ‘;  //待发和曾经发送失败的都要发
var
  AFileStream: TFileStream;
  cmd:string;
  DllPaht: string; // DLL的地址
  rtn: Integer;    //巨澜的函数是否执行成功
  mtel:string;     //手机号码
  content:string; //短信内容
  SendTimes:Integer;//发送次数
  i:Integer;        //单条发送次数
  iSuccess:Integer; //发送成功条数
  price:Double;     //短信单价
  money:Double;     //发送短信金额
  INIFile:TIniFile;
  MyCs:TRTLCriticalSection;//临界区

  procedure UpdateStatusDate;  //更新状态时间(不论成功或者失败)
  begin
    with ADOQuery3 do
    begin
      Close;                              
      sql.Clear;
      SQL.Text:=‘update sms_msg_server set status_date=:statusdate ‘+
        ‘ mtel:=:mtel and ‘+
        ‘ create_date=:createdate ‘;                  //create_date是唯一的
      Parameters.ParamByName(‘status_date‘).Value:=Now;
      Parameters.ParamByName(‘mtel‘).Value:=ADOQuery2.fieldbyname(‘mtel‘).AsString;
      Parameters.ParamByName(‘create_date‘).Value:=ADOQuery2.fieldbyname(‘create_date‘).AsDateTime;
      ExecSQL;
    end;
  end;
 
begin
  InitializeCriticalSection(MyCs);//初始化临界区
  with AThread.Connection do
  begin
    cmd := UpperCase(ReadLn);
    if cmd=‘BEGIN‘ then
    begin
      EnterCriticalSection(MyCs); //进入临界区,从流生成文本文件,以及将该文本文件写进数据表这一段要使用临界区保护
      try
        AFileStream := TFileStream.Create(FFileName, fmCreate);//建立文件流准备接收
        try
          ReadStream(AFileStream, -1, true);                  //读入全部直到结束connect
          Application.ProcessMessages;
        finally
          AFileStream.Free;                                   //释放文件流
        end;
        if not TxtToDataset(ADOQuery1,FFileName,‘,‘) then    //将文本文件写入数据库
          Application.MessageBox(‘文本写入数据库失败‘, ‘错误‘, MB_OK +
            MB_ICONSTOP);
      finally
        LeaveCriticalSection(MyCs);                          //离开临界区
      end;
      //将短信发送给巨澜短信网关
      //登录巨澜
      if (OneHandle=0) or (pRtnHandle=0) then begin         //未登录
      DllPaht := ExtractFilePath(Application.ExeName) + ‘\JL_ISP.dll‘; //获得DLL的地址
      OneHandle := LoadLibrary(Pchar(DllPaht)); //动态载入DLL,并返回其句柄
      try
          if OneHandle <> 0 then               //如果载入DLL成功则获取DLL函数的地址
              begin
                  @JL_TCPLogin := GetProcAddress(OneHandle, ‘JL_TCPLogin‘);
                  @JL_Logout := GetProcAddress(OneHandle, ‘JL_Logout‘);
                  @JL_GetAccountPrice := GetProcAddress(OneHandle, ‘JL_GetAccountPrice‘);
                  @JL_GetAccountBalance := GetProcAddress(OneHandle, ‘JL_GetAccountBalance‘);
                  @JL_ModifyPassword := GetProcAddress(OneHandle, ‘JL_ModifyPassword‘);
                  @JL_GetOneReport := GetProcAddress(OneHandle, ‘JL_GetOneReport‘);
                  @JL_GetOneSM := GetProcAddress(OneHandle, ‘JL_GetOneSM‘);
                  @JL_GetOneSM_Ex := GetProcAddress(OneHandle, ‘JL_GetOneSM_Ex‘);
                  @JL_SingleSendMsg := GetProcAddress(OneHandle, ‘JL_SingleSendMsg‘);
                  @JL_SendMsg := GetProcAddress(OneHandle, ‘JL_SendMsg‘);
              end;
          if not (@JL_TCPLogin = nil) then                   //登录巨澜服务器
              begin
                  rtn := JL_TCPLogin(                       //函数定义见Type部分。
                      ‘http://www.surge.com.cn/
                      6688,
                      Pchar(fusername),
                      Pchar(fpws),
                      2,
                      @pRtnHandle);
                  ShowResultMsg(rtn);
                  if rtn <> 0 then
                      begin
                          pRtnHandle := 0;
                          OneHandle := 0;
                      end;
              end
          else
              RaiseLastOSError;                              //报错
      except
          MessageBox(Handle, ‘系统严重错误,请重新登陆!!‘, ‘Surge‘, MB_ICONASTERISK);
      end;
      end;
      //单条短信循环发送
      with ADOQuery2 do
      begin
        Close;
        SQL.Clear;
        SQL.Text:=‘select * from sms_msg_server ‘+   //status:0/1/2 待发/成功/失败
          ‘ where status=0 or status=2 ‘;           //发送待发和发送失败的短信
        Open;
      end;
      if ADOQuery2.IsEmpty then exit;
      iSuccess:=0;                                 //初始化发送成功短信条数变量
      ADOQuery2.First;
      while not ADOQuery2.Eof do
      begin
        //发送前要检查客户的剩余短信条数,等于0则不允许发送,跳转下一条记录
        with ADOQuery4 do
        begin
          Close;
          SQL.Clear;
          SQL.Text:=‘ select user_leftamounts from sms_user ‘+
            ‘ where user_name=:username ‘;
          Parameters.ParamByName(‘user_name‘).Value:=ADOQuery2.fieldbyname(‘shop_name‘).AsString;
          Open;
        end;
        if ADOQuery4.FieldByName(‘user_leftamounts‘).Value<=0 then  //帐户余额不足
        begin
          Application.MessageBox(PChar(ADOQuery2.fieldbyname(‘shop_name‘).AsString+‘的余额已不足‘),
            ‘警告‘, MB_OK + MB_ICONWARNING);
          exit;
        end;  

        mtel:=ADOQuery2.fieldbyname(‘mtel‘).AsString;               //目标手机号
        content:=ADOQuery2.fieldbyname(‘content‘).AsString;         //短信内容

        if (pRtnHandle = 0) or (OneHandle = 0) then                 //判断是否登陆
            begin
                MessageBox(Handle, ‘你还没有登陆!‘, ‘Surge‘, MB_ICONASTERISK);
                exit;
            end;
             
        SendTimes:=ADOQuery2.fieldbyname(‘send_times‘).AsInteger; //短信发送次数
        for i:=1 to sendtimes do
        try
            rtn := JL_SingleSendMsg(pRtnHandle, //函数定义见Type部分。
                PChar(IntToStr(i)),     //自定义编号-以对应相应的状态报告,每次发送应传入不同的值,用以对应收取到的状态报告  
                ‘‘,                     //扩展端口号
                PChar(Trim(mtel)),      //群发时号码用逗号分隔,TCP协议一次群发最多50个号码。HTTP协议一次群发最多100个号码。
                PChar(Trim(content)),   //内容长度为按 Unicode characters  类型计算 ,总长度不可以超过70个字(包含签名)
                ‘‘);                    //发送时间,暂不支持!

            if rtn = 0 then            //发送成功
                begin
                    Inc(iSuccess);                         //累加发送成功条数
                    ADOQuery3.Connection.BeginTrans;       //开始事务
                    //计算发送费用
                    INIFile:=TIniFile.Create(GetINIFile);
                    try
                      price:=INIFile.ReadFloat(‘server‘,‘price‘,0.6); //获取短信的单价
                    finally
                      INIFile.Free;
                    end;
                    money:=iSuccess*price;                            //发送条数*单价
                    with ADOQuery3 do                                 //更新用户余额,剩余条数
                    begin
                      Close;
                      SQL.Clear;
                      sql.Text:=‘update sms_user ‘+
                        ‘ set user_leftmoney=user_leftmoney-:money, ‘+
                        ‘ user_leftamounts=user_leftamounts-:amounts ‘+
                        ‘ where user_name=:username ‘;
                      Parameters.ParamByName(‘user_leftmoney‘).Value:=money;
                      Parameters.ParamByName(‘user_leftamounts‘).Value:=iSuccess;
                      Parameters.ParamByName(‘user_name‘).Value:=ADOQuery2.fieldbyname(‘shop_name‘).AsString;
                      ExecSQL;
                    end;  
                    with ADOQuery3 do                                   //更新状态为发送成功
                    begin
                      Close;
                      sql.Clear;
                      SQL.Text:=‘update sms_msg_server set status=1 ‘+
                        ‘ where status=0 and  ‘+
                        ‘ mtel:=:mtel and ‘+
                        ‘ create_date=:createdata ‘;
                      Parameters.ParamByName(‘mtel‘).Value:=ADOQuery2.fieldbyname(‘mtel‘).AsString;
                      Parameters.ParamByName(‘create_date‘).Value:=ADOQuery2.fieldbyname(‘create_date‘).AsDateTime;
                      ExecSQL;
                    end;
                    UpdateStatusDate;                     //更新状态时间
                    try
                      ADOQuery3.Connection.CommitTrans;   //提交事务
                    except
                      ADOQuery3.Connection.RollbackTrans; //回滚事务
                    end;  
                    MessageBox(Handle, ‘成功发送!‘, ‘Surge‘, MB_ICONASTERISK);
                end
            else                                          //发送失败
                begin
                    ADOQuery3.Connection.BeginTrans;      //开始事务
                    with ADOQuery3 do
                    begin
                      Close;
                      sql.Clear;
                      SQL.Text:=‘update sms_msg_server set status=2 ‘+   //更新状态为发送失败
                        ‘ where status=0 and  ‘+
                        ‘ mtel:=:mtel and ‘+
                        ‘ create_date=:createdate ‘;
                      Parameters.ParamByName(‘mtel‘).Value:=ADOQuery2.fieldbyname(‘mtel‘).AsString;
                      Parameters.ParamByName(‘create_date‘).Value:=ADOQuery2.fieldbyname(‘create_date‘).AsDateTime;
                      ExecSQL;
                    end;
                    UpdateStatusDate;                     //更新状态时间
                    try
                      ADOQuery3.Connection.CommitTrans;   //提交事务
                    except
                      ADOQuery3.Connection.RollbackTrans; //回滚事务
                    end;  
                    ShowResultMsg(rtn);                   //通过函数的返回值显示相应信息
                end;
        except
            on e:exception do
              MessageBox(Handle, PChar(e.Message) , ‘Surge‘, MB_ICONASTERISK);
              //‘系统严重错误,请重新登陆!!‘
        end;
        ADOQuery2.Next;                                  //发送下一条短信
      end;                    
    end;
  end;
  DeleteCriticalSection(MyCs);                          //删除临界界
end;

procedure TFormServer.BtnStartClick(Sender: TObject);          //启动SOCKET服务端
begin
  IdTCPServer1.DefaultPort := strtoint(LabeledEdit1.Text);     //端口
  if not IdTCPServer1.Active then
    try
      IdTCPServer1.Active := True;
      ListBox1.Items.Add(‘已启动‘);
    except
      ListBox1.Items.Add(‘启动失败‘);
    end;
end;

procedure TFormServer.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  IdTCPServer1.Active:=False;
end;

procedure TFormServer.BtnStopClick(Sender: TObject);
begin
  IdTCPServer1.Active:=False;
  ListBox1.Items.Add(‘已停止‘);
end;

procedure TFormServer.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
  ListBox1.Items.Add(‘来自 ‘
    + AThread.Connection.Socket.Binding.PeerIP
    + ‘ 的连接请求已被允许‘);
  AThread.Connection.WriteLn(‘欢迎连接到左右软件短信服务器‘);
end;

end.

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
连接数据库 验证用户登录信息
delphi弹出信息框大全
delphi的消息对话框
delphi中showmessage可以使用图标吗
DELPHI 获取特殊系统目录
Delphi Application Messagebox 参数详解及应用实例
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服