使用delphi+intraweb进行微信开发5—准备实现微信API,先从获取AccessToken开始
在前4讲中我们已经使iw开发的应用成功和微信进行了对接,再接下来的章节中我们开始逐一尝试和实现微信的各个API,开始前先来点准备工作 |
- 首先需要明确的是,微信的API都是通过https调用实现的,分为post方法调用和get方法调用。不需要上传数据的采用get方法(例如获取AccessToken),而需要向微信服务器提交数据的采用post方法(例如创建菜单)。
- 微信方法调用均需传递AccessToken(URL参数方式),这个AccessToken不是我们微信接入时使用的Token,这个AccessToken专门用于微信API调用,AccessToken有过期时间,而且每天有请求次数限制,据说是为了防止不良的程序调用导致微信服务器出现异常。因此在这种情况下则必须在获取AccessToken后进行保存,在即将过期前再重新获取。
好吧,让我们开始:首先定义post和get方法。这里我们采用Indy实现,不需要再安装什么第三方组件了,也没有大量并发的要求(咱们这是客户端程序),简单易用最重要。 |
/// <summary>
/// 向指定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 |
由于AccessToken在API调用中都需要使用,因此先来获取AccessToken吧,关于AccessToken的解释请看微信文档:http://mp.weixin.qq.com/wiki/14/9f9c82c1af308e3b14ba9b973f99a8ba.html
使用的微信命令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 | 凭证有效时间,单位:秒 |
3、错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):
{"errcode":40013,"errmsg":"invalid appid"}
♥ 好吧,好像还得找个Json解析的组件,嗯嗯,够麻烦的,推荐使用第三方组件“SuperObject”进行Json格式解析,不过你要非得自行进行Json字符串编解码也行,嗯,可能会累点,相信我,最好找个封装完善的Json组件,工欲善其事必先利其器,否则创建菜单什么的时候有你受的。
嗯,Json结果解析判断什么的我就不说了,再说说AccessToken的缓存问题。 |
简单说:“为了保密appsecrect,第三方需要一个access_token获取和刷新的中控服务器。而其他业务逻辑服务器所使用的access_token均来自于该中控服务器,不应该各自去刷新,否则会造成access_token覆盖而影响业务;”这个是微信文档原话,所以让我们看看怎么缓存这个东东。
先声明一个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的函数代码如下: |
procedure TWxSdkImp.GetAccessToken(const appid, appsecret: string;
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+intraweb进行微信开发5—准备实现微信API,先从获取AccessToken开始的更多相关文章
- 微信开发(2):微信js sdk分享朋友圈,朋友,获取config接口注入权限验证(转)
进行微信开发已经一阵子了,从最初的什么也不懂,到微信授权登录,分享,更改底部菜单,素材管理,等. 今天记录一下微信jssdk 的分享给朋友的功能,获取config接口注入. 官方文档走一下简单说:四步 ...
- 夺命雷公狗---微信开发53----网页授权(oauth2.0)获取用户基本信息接口(3)实现世界留言版
前面两节课我们讲的是base型的授权了,那么现在我们开始Userinfo型授权, 先来看下我们的原理图 我们这节课来做一个 世界留言版 系统 1..首先我还是在微信测试平台那里设置好回调页面的域名 2 ...
- 夺命雷公狗---微信开发51----网页授权(oauth2.0)获取用户基本信息接口(1)
如果用户在微信客户端访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,从而实现业务逻辑. 一般我们用来“数据采集”,“市场调查”,“投票”,只要授权了第三方网页,微信用户无需注册就可 ...
- 【微信开发】PC端 微信扫码支付成功之后自动跳转
场景: PC端 微信扫码支付 结果: 支付成功 自动跳转 实现思路: 支付二维码页面,写ajax请求支付状态,请求到结果,无论成功还是失败,都跳转到相应的结果页面 具体实现方法: html部分: ...
- 夺命雷公狗---微信开发52----网页授权(oauth2.0)获取用户基本信息接口(2)
我们在上一节课已经发送code给第三方了,那么这就要获取code去换取到用户的openid. 第一步:编写create_baseurl.php(上一节课程已经写完了) 第二步:编写vote1.php( ...
- Java企业微信开发_15_查询企业微信域名对应的所有ip
一.前言 二.方法 1.在线网站 百度搜索"域名查IP",可查到如下网站,输入域名即可查到所有IP: 站长工具 site.ip138.com tools.ipip.net 2.li ...
- 使用delphi+intraweb进行微信开发3—微信消息处理
示例代码已经放出!请移步使用delphi+intraweb进行微信开发1~4代码示例进行下载,虽为示例代码但是是从我项目中移出来的,封装很完备适于自行扩展和修改. 在第二讲使用delphi+intra ...
- 【微信开发】公众号后台设置错误导致的微信redirect_uri参数错误【图】
在微信开发中,如微信网页授权登录,分享到朋友圈自定义内容,微信h5支付时 可能会遇到微信redirect_uri参数错误的情况. 此时除了检查自己代码正确性外,还要检查一下是否正确地设置了公众号后台的 ...
- c#微信开发,使用JS-SDK自定义分享功能,分享朋友圈,分享给朋友等
如果一个后端开发掌握了微信开发,甚至有微信开发上线项目,这在换工作的时候 还是有竞争力的. 微信开发的资料很多,但是用asp.net c#进行微信开发好像比较少,或者资料不够完整. 使用JS-SDK自 ...
随机推荐
- mysql二进制文件操作语法(mysql binary log operate statements)
开启 binary logs 功能 在 mysql 配置文件中配置 log-bin,重启 mysql my.cnf (on Linux/unix) or my.ini (on Windows) 例子: ...
- 2.4G无线射频通信模块nRF24L01+开发笔记(基于MSP430RF6989与STM32f0308)(1.(2)有错误,详见更正)
根据网上的nRF24L01+例程和TI提供的MSP430RF6989的硬件SPI总线例程编写程序,对硬件MSP-EXP430RF6989 Launch Pad+nRF24L01P射频模块(淘宝购买)进 ...
- C(++) Websocket消息推送---GoEasy
Goeasy, 它是一款第三方推送服务平台,使用它的API可以轻松搞定实时推送!个人感觉goeasy推送更稳定,推送 速度快,代码简单易懂上手快 浏览器兼容性:GoEasy推送 支持websocket ...
- SolidWorks的简单介绍及基本用法
写这博客的动机来源于构建之法微信群里面的的一位老师.sw是一个强大的机械设计制图软件,我记得大一的时候学制图学的3d软件是inventor,而后发现sw用起来更方便更高效,于是就自学了sw,由于是自学 ...
- 移动端bug~~移动端:active伪类无效的解决方法【移动端 :active样式无效】
移动端:active伪类无效的解决方法[移动端 :active样式无效]2016-09-26 15:46:50 问题: 移动端开发的时候实现按钮的点击样式变化,但是在iphone[safiri Mo ...
- 另类分析SIGSEGV信号
关于SIGSEGV信号的含义就不解释了.网络上有很多解释. 今天记录一下,自己遇到的一个问题,想了好几天都没想出来的.今天终于想到原因了. 过程描述: 有个类 CBase,里面放了一个成员变量 DAT ...
- OpenCV MAT基本图像容器
参考博客: OpenCv中cv::Mat和IplImage,CvMat之间的转换 Mat - 基本图像容器 Mat类型较CvMat和IplImage有更强的矩阵运算能力,支持常见的矩阵运算(参照Mat ...
- Android Context 上下文 你必须知道的一切
本文转载于:http://blog.csdn.net/lmj623565791/article/details/40481055 转载请标明出处:http://blog.csdn.net/lmj623 ...
- Web跨域问题总结
一.跨域问题的由来为了防止某些文档或脚本加载别的域下的未知内容造成泄露隐私,破坏系统等安全行为,1995年, Netscape 公司在浏览器中引入同源策略/SOP(Same origin policy ...
- 事件event_scheduler
1.查看事件是否开启 1-1.show variables like 'event_scheduler'; 1-2.select @@event_scheduler; ...