当前位置:   article > 正文

Delphi Http Https 最好的解决方法(一)_delphi tls

delphi tls

当前文章主要解决Delphi调用http、https的常见报错。

开发工具: Delphi XE 10.1 Berlin版本

可能所需的控件包: QDAC 请自行下载。

1. 接口描述

  dll_init 接口初始化,程序启动时调用,主要是对工具类实例的创建
  dll_post 发送post请求,支持http、https
  dll_get 发送get请求,支持http、https
  dll_uninit 接口释放,程序关闭时调用,主要是对工具类实例的释放

2. 参数说明

function dll_post(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte; stdcall;

function dll_get(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte; stdcall;

sUrl: 请求地址

sJson: 请求的入参,JSON格式如下(这个json只是一个例子,也可以是其他复杂json入参):

  1. {
  2. "loginName": "*****",
  3. "loginPass": "*****"
  4. }

sHeader: 请求头,固定格式如下,如果没有请求头,传空值:

  1. {
  2. "params":[
  3. {"key":"key1","value":"value1"},
  4. {"key":"key2","value":"value2"},
  5. ]
  6. }

sOut: 输出请求返回的数据信息

请求返回值 Byte类型 0 失败 1 成功

3. 完整代码如下

3.1 工具类

工具类实际就是内部创建了indy对象,一个用于http请求,一个用于https请求。

  1. unit unt_objects;
  2. interface
  3. uses
  4. Winapi.Windows, Winapi.Messages, IdHTTP, IdSSLOpenSSL, System.SysUtils,
  5. System.Classes, System.IniFiles, System.StrUtils, System.Variants,
  6. Winapi.Security.Cryptography, Winapi.WinRT, Winapi.CommonTypes, System.Win.WinRT,
  7. Contnrs, Vcl.ExtCtrls, System.DateUtils;
  8. const
  9. Err_02= '创建对象失败...';
  10. GFileName= 'set.ini';
  11. type
  12. //普通Http请求
  13. TTools= class
  14. private
  15. FDebug : Boolean; //调试模式
  16. FHttp : TIdHTTP; //HTTP专用
  17. FHttps : TIdHTTP; //HTTPS专用
  18. FBusy : Boolean; //是否忙碌
  19. FIdSSL : TIdSSLIOHandlerSocketOpenSSL;
  20. procedure DisConnect(bHttps: Boolean);
  21. published
  22. property _debug: Boolean read FDebug write FDebug;
  23. property _Https: TIdHTTP read FHttps write FHttps;
  24. property _Http: TIdHTTP read FHttp write FHttp;
  25. property _Busy: Boolean read FBusy write FBusy;
  26. public
  27. constructor Create();
  28. destructor Destroy; override;
  29. //发送Post请求
  30. function SendPost(bHttps: Boolean; sUrl, sJson: PWideChar; var sOut: PWideChar): Byte;
  31. //发送Get请求
  32. function SendGet(bHttps: Boolean; sUrl, sJson: PWideChar; var sOut: PWideChar): Byte;
  33. end;
  34. implementation
  35. uses uPub;
  36. { TTools }
  37. constructor TTools.Create;
  38. var
  39. sIni: TIniFile;
  40. begin
  41. FHttp := Tidhttp.Create(nil);
  42. FHttp.HTTPOptions := [hoKeepOrigProtocol]; //关键参数, 关系到编码自动转换
  43. FHttp.HandleRedirects:= True;
  44. FHttp.ProtocolVersion:= pv1_1;
  45. FHttp.Request.Accept:= '*/*';
  46. FHttp.Request.ContentType:= 'application/json;charset=UTF-8';
  47. FHttp.Request.Connection:= 'close';
  48. FHttp.ReadTimeout:= 30* 1000;
  49. FHttp.ConnectTimeout:= 30* 1000;
  50. FHttps := Tidhttp.Create(nil);
  51. FHttps.HTTPOptions := [hoKeepOrigProtocol];
  52. FHttps.HandleRedirects:= True;
  53. FHttps.ProtocolVersion:= pv1_1;
  54. FHttps.Request.Accept:= '*/*';
  55. FHttps.Request.ContentType:= 'application/json;charset=UTF-8';
  56. FHttps.Request.Connection:= 'close';
  57. FHttps.ReadTimeout:= 30* 1000;
  58. FHttps.ConnectTimeout:= 30* 1000;
  59. FIdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  60. FIdSSL.SSLOptions.Method:= sslvSSLv23;
  61. FIdSSL.SSLOptions.Mode:= sslmClient;
  62. if FileExists(ExtractFilePath(Paramstr(0))+GFileName) then
  63. begin
  64. sIni:= TIniFile.Create(ExtractFilePath(Paramstr(0))+GFileName);
  65. try
  66. case sIni.ReadInteger('hq','sslver',1) of
  67. 0: FIdSSL.SSLOptions.Method:= sslvSSLv2;
  68. 1: FIdSSL.SSLOptions.Method:= sslvSSLv23;
  69. 2: FIdSSL.SSLOptions.Method:= sslvSSLv3;
  70. 3: FIdSSL.SSLOptions.Method:= sslvTLSv1;
  71. 4: FIdSSL.SSLOptions.Method:= sslvTLSv1_1;
  72. 5: FIdSSL.SSLOptions.Method:= sslvTLSv1_2;
  73. end;
  74. finally
  75. FreeAndNil(sIni);
  76. end;
  77. end;
  78. FHttps.IOHandler:= FIdSSL;
  79. end;
  80. destructor TTools.Destroy;
  81. begin
  82. if Assigned(FHttps) then
  83. FreeAndNil(FHttps);
  84. if Assigned(FHttp) then
  85. FreeAndNil(FHttp);
  86. inherited;
  87. end;
  88. procedure TTools.DisConnect(bHttps: Boolean);
  89. begin
  90. if bHttps then
  91. begin
  92. if FHttps.Connected then
  93. FHttps.Disconnect;
  94. end
  95. else
  96. begin
  97. if FHttp.Connected then
  98. FHttp.Disconnect;
  99. end;
  100. end;
  101. function TTools.SendGet(bHttps: Boolean; sUrl, sJson: PWideChar; var sOut: PWideChar): Byte;
  102. var
  103. ResponseStream: TStringStream;
  104. begin
  105. Result:= 0;
  106. sOut:= '';
  107. DisConnect(bHttps);
  108. ResponseStream:= TStringStream.Create('', TEncoding.UTF8);
  109. try
  110. try
  111. systemLog('Snd: '+ sJson);
  112. FHttps.Get(sUrl, ResponseStream);
  113. sOut:= PWideChar(UTF8Decode(AnsiToUtf8(ResponseStream.DataString)));
  114. systemLog('Rcv: '+ sOut);
  115. Result:= 1;
  116. except
  117. on e: Exception do
  118. begin
  119. systemLog('exp: '+ e.Message);
  120. end;
  121. end;
  122. finally
  123. DisConnect(bHttps);
  124. end;
  125. end;
  126. function TTools.SendPost(bHttps: Boolean; sUrl, sJson: PWideChar; var sOut: PWideChar): Byte;
  127. var
  128. ResquestStream,ResponseStream : TStringStream;
  129. begin
  130. Result:= 0;
  131. sOut:= '';
  132. DisConnect(bHttps);
  133. try
  134. systemLog('Snd: '+ sJson);
  135. ResquestStream := TStringStream.Create(UTF8Encode(sJson));
  136. ResponseStream := TStringStream.Create('', TEncoding.UTF8);
  137. //ResponseStream := TStringStream.Create('');
  138. try
  139. if bHttps then
  140. FHttps.Post(sUrl, ResquestStream, ResponseStream)
  141. else
  142. FHttp.Post(sUrl, ResquestStream, ResponseStream);
  143. sOut := PWideChar(UTF8Decode(AnsiToUtf8(ResponseStream.DataString)));
  144. //sOut := PWideChar(UTF8Decode(WideString(ResponseStream.DataString)));
  145. systemLog('Rcv: '+ sOut);
  146. Result:= 1;
  147. except
  148. on e: Exception do
  149. systemLog('Exp: '+ e.Message);
  150. end;
  151. finally
  152. DisConnect(bHttps);
  153. end;
  154. end;
  155. end.

3.2 公共类

  1. unit uPub;
  2. interface
  3. uses
  4. System.SysUtils, System.Classes, qaes, qstring, IdHashMessageDigest, IdHash;
  5. type
  6. TMD5= class(TIdHashMessageDigest5);
  7. TAppPara = class
  8. public
  9. class function AppPath: string;
  10. class function AppName: string;
  11. end;
  12. TFilePath = class(TAppPara)
  13. public
  14. class function IniFile: string;
  15. end;
  16. //写日志
  17. procedure systemLog(Msg: AnsiString);
  18. //AES对象初始化
  19. procedure InitEncrypt(sKey, sIv: PWideChar; aesModel, keyType, paddingmodel: integer; var AES: TQAES);
  20. //字符串转MD5
  21. function StrToMD5(sIn: WideString): WideString;
  22. implementation
  23. procedure systemLog(Msg: AnsiString);
  24. var
  25. F: TextFile;
  26. FileName: string;
  27. ExeRoad: string;
  28. begin
  29. try
  30. ExeRoad := ExtractFilePath(ParamStr(0));
  31. if ExeRoad[Length(ExeRoad)] = '\' then
  32. SetLength(ExeRoad, Length(ExeRoad) - 1);
  33. if not DirectoryExists(ExeRoad + 'log') then
  34. begin
  35. CreateDir(ExeRoad + '\log');
  36. end;
  37. FileName := ExeRoad + '\log\DLL_Log' + FormatDateTime('YYMMDD', NOW) + '.txt';
  38. if not FileExists(FileName) then
  39. begin
  40. AssignFile(F, FileName);
  41. ReWrite(F);
  42. end
  43. else
  44. AssignFile(F, FileName);
  45. Append(F);
  46. Writeln(F, FormatDateTime('HH:NN:SS.zzz ', Now) + Msg);
  47. CloseFile(F);
  48. except
  49. //可能在事务中调用,避免意外
  50. Exit;
  51. end;
  52. end;
  53. procedure InitEncrypt(sKey, sIv: PWideChar; aesModel, keyType, paddingmodel: integer; var AES: TQAES);
  54. var
  55. AInitVector: TQAESBuffer;
  56. AKeyType: TQAESKeyType;
  57. I: Integer;
  58. begin
  59. case keyType of
  60. 0:
  61. AKeyType := kt128;
  62. 1:
  63. AKeyType := kt192;
  64. 2:
  65. AKeyType := kt256;
  66. end;
  67. if aesModel= 0 then
  68. AES.AsECB(sKey, AKeyType)
  69. else
  70. begin
  71. for I := 1 to Length(sIv) do
  72. AInitVector[I-1]:= byte(sIv[I-1]);
  73. AES.AsCBC(AInitVector, sKey, AKeyType);
  74. end;
  75. //AES.PaddingMode在AES.AsECB AES.AsCBC中是默认值的 所以在以下进行单独设置
  76. case paddingmodel of
  77. 0:
  78. AES.PaddingMode:= pmZero;
  79. 1:
  80. AES.PaddingMode:= pmPKCS5;
  81. 2:
  82. AES.PaddingMode:= pmPKCS7;
  83. end;
  84. end;
  85. //字符串转MD5
  86. function StrToMD5(sIn: WideString): WideString;
  87. var
  88. Md5Encode: TMD5;
  89. begin
  90. Md5Encode:= TMD5.Create;
  91. result:= Md5Encode.HashToHex(Md5Encode.HashString(UTF8Encode(sIn)));
  92. Md5Encode.Free;
  93. end;
  94. { TAppPara }
  95. class function TAppPara.AppName: string;
  96. begin
  97. Result := ExtractFileName(ParamStr(0));
  98. end;
  99. class function TAppPara.AppPath: string;
  100. begin
  101. Result := ExtractFilePath(ParamStr(0));
  102. end;
  103. { TFilePath }
  104. class function TFilePath.IniFile: string;
  105. begin
  106. Result := AppPath + 'set.ini';
  107. end;
  108. end.

3.3 接口类

  1. unit InterfaceDll;
  2. interface
  3. uses
  4. unt_objects, Winapi.Windows, System.SysUtils, System.Classes, EncdDecd, Qjson;
  5. var
  6. tool: TTools;
  7. pools: THttpConnectopnPool;
  8. //----------------------------------测试部分------------------------------------
  9. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  10. //测试
  11. function dll_test: Byte; stdcall;
  12. //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  13. //-------------------------普通 网络请求部分------------------------------------
  14. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  15. //初始化
  16. function dll_init: Byte; stdcall;
  17. //Post
  18. function dll_post(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte; stdcall;
  19. //Get
  20. function dll_get(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte; stdcall;
  21. //释放
  22. function dll_uninit: Byte; stdcall;
  23. //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  24. implementation
  25. uses uPub, uSuperObject, qaes;
  26. //测试
  27. function dll_test: Byte; stdcall;
  28. begin
  29. Result:= 1;
  30. end;
  31. //-------------------------普通 网络请求部分------------------------------------
  32. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  33. //初始化
  34. function dll_init: Byte;
  35. begin
  36. Result:= 0;
  37. if not Assigned(tool) then
  38. tool:= TTools.Create;
  39. Result:= 1;
  40. end;
  41. /// <summary>
  42. /// POST请求
  43. /// </summary>
  44. function dll_post(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte;
  45. var
  46. json, jsArr: TQjson;
  47. I:integer;
  48. bHttps: Boolean;
  49. begin
  50. Result:= 0;
  51. bHttps:= (Pos('https:', sUrl)>0);
  52. if Assigned(tool) then
  53. begin
  54. if tool._debug then
  55. systemLog('[dll_post]: '+ AnsiString(sJson));
  56. json:= TQJson.Create;
  57. try
  58. json.Parse(sHeader);
  59. tool._Https.Request.CustomHeaders.Clear;
  60. jsArr:= json.ItemByName('params');
  61. if jsArr<> nil then
  62. begin
  63. for I := 0 to jsArr.Count- 1 do
  64. tool._Https.Request.CustomHeaders.Values[jsArr.Items[I].ValueByName('key','')]:= jsArr.Items[I].ValueByName('value','')
  65. end;
  66. finally
  67. FreeAndNil(json);
  68. end;
  69. Result:= tool.SendPost(bHttps, sUrl, sJson, sOut);
  70. end
  71. else
  72. begin
  73. systemLog('[dll_post]: '+ Err_02);
  74. Exit;
  75. end;
  76. end;
  77. //Get
  78. function dll_get(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte;
  79. var
  80. json: ISuperObject;
  81. jsArr: TSuperArray;
  82. I:integer;
  83. bHttps: Boolean;
  84. begin
  85. Result:= 0;
  86. sOut:= '';
  87. bHttps:= (Pos('https:', sUrl)>0);
  88. if Assigned(tool) then
  89. begin
  90. if tool._debug then
  91. systemLog('[dll_post]: '+ AnsiString(sJson));
  92. if sHeader<>'' then
  93. json:= SO(sHeader);
  94. if json<>nil then
  95. begin
  96. tool._Https.Request.CustomHeaders.Clear;
  97. jsArr:= json.O['headers'].AsArray;
  98. for I := 0 to jsArr.Length- 1 do
  99. begin
  100. if bHttps then
  101. tool._Https.Request.CustomHeaders.Values[jsArr.O[I].S['key']]:= jsArr.O[I].S['value']
  102. else
  103. tool._Https.Request.CustomHeaders.Values[jsArr.O[I].S['key']]:= jsArr.O[I].S['value'];
  104. end;
  105. end;
  106. Result:= tool.SendGet(bHttps, sUrl, sJson, sOut);
  107. end
  108. else
  109. begin
  110. systemLog('[dll_get]: '+ Err_02);
  111. Exit;
  112. end;
  113. end;
  114. //释放
  115. function dll_uninit: Byte;
  116. begin
  117. result:= 0;
  118. if Assigned(tool) then
  119. FreeAndNil(tool);
  120. result:= 1;
  121. end;
  122. //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  123. end.

3.4 工程文件

  1. uses
  2. System.SysUtils,
  3. System.Classes,
  4. unt_objects in 'unt_objects.pas',
  5. uPub in 'uPub.pas',
  6. InterfaceDll in 'InterfaceDll.pas' {$R *.res},
  7. uSuperObject in '..\public\uSuperObject.pas';
  8. {$R *.res}
  9. exports
  10. dll_init,
  11. dll_post,
  12. dll_get,
  13. dll_uninit;
  14. begin
  15. end.

4. Demo引用

  1. const
  2. dllName= 'HelpTool.dll';
  3. //普通网络请求部分
  4. function dll_init: Byte; stdcall; external dllName;
  5. function dll_post(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte; stdcall; external dllName;
  6. function dll_get(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte; stdcall; external dllName;
  7. function dll_uninit: Byte; stdcall; external dllName;

当前运用于实际项目中,跑了2个月了,运行正常,检查日志无报错。

有需要的朋友可以自行修改设计成自己需要的。

代码虽然贴出来了,但是还是希望能够自己敲下,加深理解。

如果有好的建议,或发现问题,请留言,我也好改进、学习.

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号