使用delphi+intraweb进行微信开发5—准备实现微信API,先从获取AccessToken开始
2016-03-30 16:50
585 查看
在前4讲中我们已经使iw开发的应用成功和微信进行了对接,再接下来的章节中我们开始逐一尝试和实现微信的各个API,开始前先来点准备工作 |
微信方法调用均需传递AccessToken(URL参数方式),[u]这个AccessToken不是我们微信接入时使用的Token[/u],这个AccessToken专门用于微信API调用,AccessToken有过期时间,而且每天有请求次数限制,据说是为了防止不良的程序调用导致微信服务器出现异常。因此在这种情况下则必须在获取AccessToken后进行保存,在即将过期前再重新获取。
好吧,让我们开始:首先定义post和get方法。这里我们采用Indy实现,不需要再安装什么第三方组件了,也没有大量并发的要求(咱们这是客户端程序),简单易用最重要。 |
/// 向指定URL发起Get请求
/// </summary>
/// <param name="http">TIdHTTP</param>
/// <param name="URL">指定URL</param>
/// <param name="Max">Get请求失败最大重试次数</param>
/// <returns>返回腾讯服务器响应(string类型的json格式数据)</returns>
function GetMethod(http: TIdHTTP; URL: String; Max: Integer): String;
var
RespData: TStringStream;
begin
RespData := TStringStream.Create('', TEncoding.UTF8);
try
try
http.Get(URL, RespData);
http.Request.Referer := URL;
Result := RespData.DataString;
except
Dec(Max);
if Max = 0 then
begin
Result := '';
exit;
end;
Result := GetMethod(http, URL, Max);
end;
finally
FreeAndNil(RespData);
end;
end;
/// <summary>
/// 向指定URL提交数据(Post)
/// </summary>
/// <param name="http">TIdHTTP</param>
/// <param name="URL">指定URL</param>
/// <param name="Data">要提交的数据(UTF8String)</param>
/// <param name="Max">Post请求失败最大重试次数</param>
/// <returns>返回腾讯服务器响应(string类型的json格式数据)</returns>
function PostMethod(http: TIdHTTP; URL: String; Data: UTF8String;
Max: Integer): String;
var
PostData, RespData: TStringStream;
begin
RespData := TStringStream.Create('');
PostData := TStringStream.Create(Data);
try
try
if http = nil then
exit;
http.Post(URL, PostData, RespData);
Result := RespData.DataString;
http.Request.Referer := URL;
except
Dec(Max);
if Max = 0 then
begin
Result := '';
exit;
end;
Result := PostMethod(http, URL, Data, Max);
end;
finally
http.Disconnect;
FreeAndNil(RespData);
FreeAndNil(PostData);
end;
end;
有了上面两个方法我们就可以开始测试微信API了。
♥ 不过你有没有注意到,微信请求是https,不是http啊,所以似乎还需要让Indy支持ssl传输才行啊,这当然没有问题,上Indy官网下载SSL支持DLL即可,分为64位和32位版本不要搞错,下载后和编译好的IW程序放置在同一目录下即可(说实在的下载网站我给忘了,大家可以百度一下,如果找不到给我留言,我把我下载的发出来)。
接下来研究下如何获取这个AccessToken |
使用的微信命令URL是:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
采用Get方法。
如你所见:
1、URL调用需传递【APPID】和【APPSECRET】两个参数,返回结果为Json格式字符串。
2、调用成功的情况下,微信会返回下述JSON数据包给公众号:
{"access_token":"ACCESS_TOKEN","expires_in":7200}
参数 | 说明 |
---|---|
access_token | 获取到的凭证 |
expires_in | 凭证有效时间,单位:秒 |
{"errcode":40013,"errmsg":"invalid appid"}
♥ 好吧,好像还得找个Json解析的组件,嗯嗯,够麻烦的,推荐使用第三方组件“SuperObject”进行Json格式解析,不过你要非得自行进行Json字符串编解码也行,嗯,可能会累点,相信我,最好找个封装完善的Json组件,工欲善其事必先利其器,否则创建菜单什么的时候有你受的。
嗯,Json结果解析判断什么的我就不说了,再说说AccessToken的缓存问题。 |
先声明一个TAccessToken记录,然后利用一个全局公开的变量,再加上一个泛型容器,如此的简单:
/// <summary>
/// AccessToken记录,包含AccessToken值和过期时间
/// </summary>
TAccessToken = record
AccessToken: string;
AccessTokenExpiresDt: TDateTime;
end;
var
gAccessTokenLst: TDictionary<string, TAccessToken>;
gCS: TCriticalSection;
♥ 声明成记录类型的好处是,可以当做简单变量来使用,要是声明成指针或者类,哦哦,创建再释放,太麻烦了。微信返回的json结果中是这个AccessToken还有多少秒过期,我们换算成时间类型会比较好用一些。
♥ 泛型我喜欢,让Hash表成为强类型的。
♥ 如上gAccessTokenLst用来存储获取的AccessToken,key就是微信号的APPID,估计这个不会重复吧!上面还声明了一个临界区对象gCS,大约我不说你也能猜到,既然是全局的那就得上锁,防止写入混乱。
♥ 上面那两个变量gAccessTokenLst和gCS我是在单元的initialization部分实例化的,并在finalization进行了释放,在这两个地方处理全局变量的好处是:运行时只执行一次。是初始化全局变量的绝佳地点。
万事具备了,最终获取AccessToken的函数代码如下: |
var AccessToken: string; const GetNew: Boolean
= false);
var
URL: string;
JSONObject: ISuperObject;
temp, sKey: string;
recAccessToken: TAccessToken;
begin
if (appid = '') or (appsecret = '') then
raise Exception.Create('TWxSdkImp.GetAccessToken执行出错,参数应用ID或者应用秘钥不能为空!');
recAccessToken.AccessToken := '';
sKey := appid;
if gAccessTokenLst.ContainsKey(sKey) then
recAccessToken := gAccessTokenLst.Items[sKey];
// 如果要求重新获取AccessToken 或者 尚未获取AccessToken 或者 已经获取了但是离过期不足30秒
gCS.Enter;
try
if GetNew or (recAccessToken.AccessToken = '') or (SecondSpan(recAccessToken.AccessTokenExpiresDt, Now) < 30) then
begin
URL := Format(WxCmdUrl_GetAccessToken, [appid, appsecret]);
temp := GetMethod(http, URL, 3);
JSONObject := ParseJson(temp, ['"access_token"', '"errcode"']);
if Pos('"access_token"', temp) > 0 then
begin
recAccessToken.AccessToken := JSONObject['access_token'].AsString;
recAccessToken.AccessTokenExpiresDt := IncSecond(Now, JSONObject['expires_in'].AsInteger);
if gAccessTokenLst.ContainsKey(sKey) then
gAccessTokenLst.Remove(sKey);
gAccessTokenLst.Add(sKey, recAccessToken);
end else
raise Exception.Create('TWxSdkImp.GetAccessToken执行出错,服务器返回错误代码:' + JSONObject['errcode'].AsString + ',错误信息:' + JSONObject['errmsg'].AsString + '!');
end;
finally
gCS.Leave;
end;
AccessToken := recAccessToken.AccessToken;
end;
需要获取AccessToken时,
var
accessToken: string;
GetAccessToken('YourAppID',
'YourAppSecret', accessToken);
输出的accessToken字符串就是我们想要的结果。
♥ 呵呵,如果想要用Delphi+iw进行微信开发的,看到这里应该算是有方向了吧,加油!希望早日看到各位的大作。
相关文章推荐
- Delphi 静态局部变量的替换方法
- Delphi下载指定网址(URL)的文件,带进度条显示
- 使用delphi+intraweb进行微信开发5—准备实现微信API,先从获取AccessToken开始
- Delphi下的原生ADO使用方法
- 在delphi中三个形式:ADODB_TLB ADOInt ADODB
- Delphi的没落有三个原因(比较贴切)
- delphi locate多字段查询
- Delphi5 update1的序列号
- TSrings 使用
- Delphi多线程Timer
- delphi 解决屏幕闪烁
- 问题-Delphi2007编译时提示内存错误“sxs.dll. No Debug Info.ACCESS 0xXXXXX"
- Delphi CxGrid用法详解
- Delphi快捷键
- delphi 自定义内存管理
- 大端、小端 模式
- 在.net中调用Delphi dll的Pchar转换
- 解析Delphi中常用的多种形式消息框
- Delphi XE Seattle update1 调试iOS 9.3程序时,不能用真机调试的问题
- Delphi XE Seattle update1 在iOS 9.3模拟器调试程序时出现dlopen(libmidas.dylib,1):image not found错误的解决