微信开发判断token是否有效

2016-05-06 09:24:32 zhangxc0310 阅读数 30415

做微信开发的人都知道,access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token,我前几天做项目的时候,偶尔会有好多用户的信息获取不到,还有生成二维码报错,打印log才发现,access_token已经失效,但access_token的有效期是7200S也就是两个小时,但我的token失效的时候才30分钟左右,其他地方也没有单独调用获取token的接口,让人匪夷所思。

实在没有办法了,只能用一个迂回的招,就是调用微信一个没有次数限制的接口,把access_token传过去,接受返回值判断token的有效性。



首先是判断token的有效期 

<pre name="code" class="csharp">public string isExpires() { 
string sqlStr = "select ACCESS_TOKEN,ROW_ID,END_DATE from CD_TOKEN where DELETE_FLAG='N'"; 
//进行判断 
string nowTag = getTimestamp();
//当前时间的秒数 
DataSet ds=dao.GetDataSet(sqlStr); 
if (ds.Tables[0].Rows.Count == 1) 
{ 
if (Convert.ToInt32(ds.Tables[0].Rows[0]["END_DATE"].ToString()) > Convert.ToInt32(nowTag)) 
{ 
return ds.Tables[0].Rows[0]["ACCESS_TOKEN"].ToString(); 
} else { 
return "false"; 
}
 } 
return "false"; 
}





然后重点来了,当token没有过期,但已经失效的情况怎么办呢。

<pre name="code" class="csharp">public string GetNewAccess_token() {
 //判断access-token是否有效?
 string result = access_tokenDao.isExpires(); 
if (result == "false")//无效 
{ 
//刷新access_token 
string token = GetAccess_token().access_token;
//获取最新的access_token 
//将新的token存入进数据库 
string startDate = getTimestamp(); 
string endDate = (Convert.ToInt32(startDate) + 6000) + ""; 
Boolean t = access_tokenDao.refreshToken(token, startDate, endDate, "7200"); 
return token; } 
//调用第三个接口,验证token有效性 
string url = "https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token="+result; 
string ip = new ApplicationUtil().DealGet(url);
 //Log.Info("err", s); 
IPtest iptest = new IPtest(); 
iptest = WXJSONHelper.ParseFromJson<iptest>(ip); 
string errorcode = iptest.errcode; 
if (errorcode != null) 
{ 
string token = GetAccess_token().access_token;
//获取最新的access_token 
//将新的token存入进数据库 
string startDate = getTimestamp(); 
string endDate = (Convert.ToInt32(startDate) + 6000) + ""; 
Boolean t = access_tokenDao.refreshToken(token, startDate, endDate, "7200"); 
return token; 
}
 return result; 
}






差不多就这样吧,第一次写。。。





2016-04-07 16:23:46 ly20116 阅读数 6966

转载请注明:http://blog.csdn.net/ly20116/article/details/51086662

一、access_token简介
access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,每日调用限制2000次需定时刷新,重复获取将导致上次获取的access_token失效。
目前access_token的有效期通过返回的expire_in来传达,目前是7200秒之内的值。
二、接口说明

http请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

注意是https协议,调用所有微信接口时均需使用https协议。

参数说明:
这里写图片描述
返回说明:
正确返回数据:

 {"access_token":"ACCESS_TOKEN","expires_in":7200}

参数说明:
这里写图片描述

错误返回数据:
{“errcode”:40013,”errmsg”:”invalid appid”}

三、创建AccessToken实体类

/**
 * 凭证类
 * @author 洋
 *
 */
public class AccessToken {
    private String token;//凭证
    private int expiresIn;//凭证有效时间
    public String getToken() {
        return token;
    }
    public void setToken(String token) {
        this.token = token;
    }
    public int getExpiresIn() {
        return expiresIn;
    }
    public void setExpiresIn(int expiresIn) {
        this.expiresIn = expiresIn;
    }

}

四、通过Https请求获取AccessToken对象

private static final String access_token_url="https://api.weixin.qq.com/cgi-bin/token?"
            + "grant_type=client_credential&appid=APPID&secret=APPSECRET";

/**
     * 获取Access_Token
     * @param appid
     * @param appsecret
     * @return
     */
    public static AccessToken getAccessToken(String appid,String appsecret){
        AccessToken accessToken=null;
        String requestUrl=access_token_url.replace("APPID",appid).replace("APPSECRET", appsecret);
        JSONObject jsonObject=httpsRequest(requestUrl, "GET", null);
        if(jsonObject!=null){
            accessToken=new AccessToken();
            accessToken.setToken(jsonObject.getString("access_token"));
            accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
        }
        return accessToken;

    }

五、access_token有效性的保持

由于access_token的有效期为2小时,且每天调用限制2000次,如果我们每次都调用接口生成新的access_token,这就会可能超出限制和资源浪费(需要重新调用接口)。(当然人只是测试时用肯定不到2000次)。所有需要定时刷新access_token,使它始终保持有效。

使用单例模式,创建单例类,运用线程定时刷新。

/**
 * AccessToken 单例类
 * @author 洋
 *
 */
public class SingleAccessToken {

    private static final String appid="APPID";//你自己的appid
    private static final String appsecret="APPSECRET";//你自己的appsecret

    private AccessToken accessToken;
    private static SingleAccessToken singleAccessToken;
    /**
     * 私有构造函数
     */
    private SingleAccessToken(){

        accessToken=HttpsUtil.getAccessToken(appid, appsecret);
        initThread();
    }
    /**
     * 获取SingleAccessToken对象
     * @return
     */
    public static SingleAccessToken getInstance(){
        if(singleAccessToken==null){
            singleAccessToken=new SingleAccessToken();
        }
        return singleAccessToken;
    }

    public AccessToken getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(AccessToken accessToken) {
        this.accessToken = accessToken;
    }
    /**
     * 开启线程,设置SingleAccessToken为空
     */
    private void initThread(){
        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                   //睡眠7000秒
                    Thread.sleep(7000*1000);    
                    singleAccessToken=null;

                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }).start();
    }

}
2016-08-31 20:07:08 zwrj1130 阅读数 5750

云服务器 ECS 服务器中微信公众平台 Token 验证失败常见原因



很多的用户的程序后台在 ECS 服务器进行微信公众平台 Token 验证是显示失败如下图:

blob.png

 



1、非正常编辑文件(记事本,在线编辑),导致添加了 utf8 的 bom 签名

建议处理办法:使用多功能编辑器去除 bom。

 

2、php 文件结束符后包含换行或其他字符

  1. //文件开始
  2. ?>
  3. //文件结束

建议处理办法:去除多余的字符。

 

3. 程序 gzip 加密异常

建议处理办法:可临时取消程序 gzip 功能排查测试。

4. 服务器用户如果安装了安全狗或者云盾可能会拦截腾讯服务器的请求

建议处理办法:卸载安全狗,或者提示云盾设置白名单。

 

5. 虚拟主机使用临时域名去验证导致被系统拦截(适用于万网的虚拟主机)

建议处理办法:使用已经接入阿里云备案的正式域名来进行验证操作。



这个问题的最佳调试工具 curl,可以模拟微信请求 api 来判断问题

  1. curl http://xxx/index.php/api/xx

我的问题:

 

是因为php文件结束时候的空格回车符导致的。 



删除空格回车后验证成功。





2016-07-07 15:02:46 wzx19840423 阅读数 55077

这真是一个巨大的坑,为了避免以后踩到同样的坑和帮助刚接触这块的同学快速脱坑,我花了些时间研究问题的来龙去脉,提供了一个不太完美的解决方案,以及未来规划的完美解决方案。

问题现象

在开发微信jssdk的图像接口功能时,测试环境和回归环境都ok。但是更新到预发布环境后,功能就异常了,一直报图片下载失败。最后快到发布时间时,功能又恢复正常了。于是按照常规流程进行了发布。过了两天,收到线上反馈的问题:用户刚开始还能正常传图,用着用着就突然报错说传图失败,然后就一直不能用了。我们在测试环境模拟测试,功能又是正常的:(

查找原因

这种偶现的问题一般都很难迅速定位到具体原因,而且本地和测试环境正常,预发布环境和线上异常,但是又不能进行调试。于是只能根据代码逻辑进行猜测性判断和尝试修复,中间走了大量的弯路,最后发现,删除存储access_token的redis值,再使用时功能正常。

技术分析

问题暂时解决了,但这不是长久之计。于是我花了点时间阅读官方文档,发现这果真是个大坑啊!官方文档原文如下:


第一个红色框里的内容,我测试了三次,第一次连续请求13遍,access_token发生了变化;第二次连续请求12遍,access_token发生了变化;第三次连续请求19遍,access_token发生了变化。(坑一)

第二个红色框里的内容,我们有开发环境,测试环境,回归环境,预发布环境,正式环境,都是同一套代码,同一个微信号,相当于每个环境都是单独的中控服务器。(坑二)

现场还原

搞清楚问题后,我们通过一些手段尝试性的触发问题现象:

1、测试环境下,清空access_token的redis数据。

2、正常测试,功能ok,查看access_token的redis内容,这里假设值为A。

3、手动调用接口刷新access_token,大概十几次后,值变化为B。

4、再次正常测试,发现功能异常(因为此时存储在redis的access_token已经过期)。

5、清空access_token的redis数据,再次测试,功能又恢复正常。

现在问题终于变成必现的了:)

解决方案

现在我们搞清楚问题的原因是存储在redis的access_token可能在很短的时间内过期(因为有太多中控服务器啦),但是我们一般设置的有效期都接近或等于7200s,这就导致一旦出现问题的话,如果不清理redis,问题就会持续2小时左右,这简直就是灾难!

目前想到的比较理想的解决方案就是:服务器发现功能异常时,刷新access_token并更新redis,然后再次调用接口。这种容错机制本来是微信的事-_-!

未来规划

正如开头所说,这的确是个巨坑,未来只能期望微信获取access_token的接口能够完善:

1、说好的2小时过期时间,就得保证2小时内不过期

2、返回的过期时间字段为还剩多少秒过期,而不是每次都返回7200s

然而微信并没有

2019-01-08 17:43:03 weixin_42125737 阅读数 2447

 

 WeChatAPIError: invalid credential, access_token is invalid or not latest
 hint: [OwEKuA02878053!]

问题: 公众号网页开发,后台使用node去微信服务器换取access_token,微信token的有效时间为7200s,但是换取的token很短的时间就失效了。

解决: 刚开始以为是代码有问题,检查之后发现并没有问题。后来发现原来如果有其他地方重新获取token,那么原来的token将在5分钟之后过期,因为同事使用了同一个公众号获取token,所以我的token很快就失效了。因此同一个公众号的APPID和appsecret在一个工程内只使用同一个接口换取token,然后存储为全局token。