java版--微信jssdk 授权config接口注入权限验证配置的参数获取+全局缓存access_token和jsapi_ticket

java版–微信jssdk 授权config接口注入权限验证配置的参数获取+全局缓存access_token和jsapi_ticket

最近的开发公众号h5,需要用的微信的扫一扫,不过微信这些功能,需要先通过config接口注入权限验证配置,翻了好多文章才弄出来,下面开始吧

JSSDK使用步骤

步骤一:绑定域名
步骤二:引入JS文件
这些我就不说了,这些微信官网都有:: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html.
我们直接开始第三步

一,授权config接口注入权限验证配置的参数获取

1.获取access_token+获取ticket

下面是获取access_token获取ticket的方法,(这里要说一下获取ticket是需要用到获取的access_token),我把这两个方法都封装到一个WeixinUtil 实体类,具体代码如下:

import com.hg.wrg.modules.qt.qtutil.MdzwUtils;
import com.hg.wrg.modules.qt.qtutil.PayConfig;
import net.sf.json.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import java.util.Map;

public class WeixinUtil {
    //获取access_token
    public  static  String getAccessToken(){
        StringBuilder url = new StringBuilder("https://api.weixin.qq.com/cgi-bin/token?");
        url.append("grant_type=");//grant_type设置
        url.append("client_credential");
        url.append("&appid=");//appid设置
        url.append("appid");//填写自己的公众号APPID
        url.append("&secret=");//secret设置
        url.append("secret");//secret
        Map<String, Object> map = null;
        try {
            HttpClient client = HttpClientBuilder.create().build();//构建一个Client
            HttpGet get = new HttpGet(url.toString());    //构建一个GET请求
            HttpResponse response = client.execute(get);//提交GET请求
            HttpEntity result = response.getEntity();//拿到返回的HttpResponse的"实体"
            String content = EntityUtils.toString(result);
            System.out.println(content);//打印返回的信息
            JSONObject res = JSONObject.fromObject(content);//把信息封装为json*/
            //把信息封装到map
            map = MdzwUtils.parseJSON2Map(res);//这个小工具的代码在下面
            System.out.println(map);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map.get("access_token").toString();

    }
    //获取ticket
    public  static  String getJsApiTicket(String accessToken){
        StringBuilder url = new StringBuilder("https://api.weixin.qq.com/cgi-bin/ticket/getticket?");
        url.append("access_token=");//code设置
        url.append(accessToken);//获取的access_token
        url.append("&type=");//appid设置
        url.append("jsapi");

        Map<String, Object> map = null;
        try {
            HttpClient client = HttpClientBuilder.create().build();//构建一个Client
            HttpGet get = new HttpGet(url.toString());    //构建一个GET请求
            HttpResponse response = client.execute(get);//提交GET请求
            HttpEntity result = response.getEntity();//拿到返回的HttpResponse的"实体"
            String content = EntityUtils.toString(result);
            System.out.println(content);//打印返回的信息
            JSONObject res = JSONObject.fromObject(content);//把信息封装为json*/
            //把信息封装到map
            map = MdzwUtils.parseJSON2Map(res);//这个小工具的代码在下面
            System.out.println(map);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map.get("ticket").toString();

    }

}

2.生成JS-SDK权限验证的签名

获得jsapi_ticket之后,我们就可以就可以生成JS-SDK权限验证的签名了。
微信
DEMO页面: https://www.weixinsxy.com/jssdk/

示例代码:
http://demo.open.weixin.qq.com/jssdk/sample.zip
备注:链接中包含php、java、nodejs以及python的示例代码供第三方参考,第三方切记要对获取的accesstoken以及jsapi_ticket进行缓存以确保不会触发频率限制。

我这里是把微信官方给的dome稍微修改一下;
下附代码:


import java.util.UUID;
import java.util.Map;
import java.util.HashMap;
import java.util.Formatter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;

/**
 * 官方给的使用js的验证工具
 */
public class JsSignUtil {
    public static String accessToken = null;

    public static Map<String, String> sign(String url) throws Exception{
        accessToken = WxAccessToken.getSavedAccessToken();
        String jsapi_ticket = WxAccessToken.getSavedJsApiTicket(accessToken);


        Map<String, String> ret = new HashMap<String, String>();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";

        //注意这里参数名必须全部小写,且必须有序
        string1 = "jsapi_ticket=" + jsapi_ticket +
                "&noncestr=" + nonce_str +
                "×tamp=" + timestamp +
                "&url=" + url;
        System.out.println("string1="+string1);

        try
        {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }

        ret.put("url", url);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        ret.put("appId", "appid");//公众号appid

        System.out.println("1.ticket(原始)="+jsapi_ticket);
        System.out.println("2.url="+ret.get("url"));
        System.out.println("3.jsapi_ticket(处理后)="+ret.get("jsapi_ticket"));
        System.out.println("4.nonceStr="+ret.get("nonceStr"));
        System.out.println("5.signature="+ret.get("signature"));
        System.out.println("6.timestamp="+ret.get("timestamp"));

        return ret;
    }


    /**
     * 随机加密
     * @param hash
     * @return
     */
    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    /**
     * 产生随机串--由程序自己随机产生
     * @return
     */
    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    /**
     * 由程序自己获取当前时间
     * @return
     */
    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
}

由于access_token和jsapi_ticket的有效期都是7200秒,且每天的请求次数有限所以我们需要把access_token和jsapi_ticket缓存起来

二,全局缓存access_token和jsapi_ticket

我这里用的是本地文件缓存,通过物理磁盘创建txt文件保存。
其他的缓存方式最后会附上连接文章,有兴趣的可以自行观看。

首先建一个 AccessToken实体类用于组装返回结果,
我是用IDEA编写
这里用了lombok插件,没用的可以自行添加get,set,和构造方法

import lombok.Data;

import java.io.Serializable;

/**
 * AccessToken实体类用于组装返回结果
 */
@Data
public class AccessToken implements Serializable {
    private String token;
    private Integer expiresIn;
    private String jsApiTicket;

}

这里依赖google的Gson jar包,如果是maven项目,下面是方式依赖

<dependency>  
    <groupId>com.google.code.gson</groupId>  
    <artifactId>gson</artifactId>  
    <version>2.7</version>  
</dependency> 

本地缓存的具体代码,里面都有注释
可以用main方法测试

import com.google.gson.Gson;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 *
 * 微信获取AccessToken并本地保存
 */
public class WxAccessToken {
    private static final long MAX_TIME = 7000;// 微信允许最长Access_token有效时间为7200秒,这里设置为7000秒

    public static String access_token_obj=null;
    /**
     * 获取Access_token 保存并且只保存2小时Access_token。如果超过两个小时重新获取;如果没有超过两个小时,直接获取
     * 思路:将获取到的Access_token和当前时间存储到file里,
     * 取出时判断当前时间和存储里面的记录的时间的时间差,如果大于MAX_TIME,重新获取,并且将获取到的存储到file替换原来的内容
     * 如果小于MAX_TIME,直接获取。
     */
    public static String getSavedAccessToken() throws IOException {
        Gson gson = new Gson();
        String mAccess_token = null;// 需要获取的Access_token;
        System.out.println(System.getProperty("user.di"));
        File file = new File("D:/weixin/weixinAccess_token.txt");// Access_token保存的位置
        // 如果文件不存在,创建
        if (!file.exists())
            file.createNewFile();
        // 如果文件大小等于0,说明第一次使用,存入Access_token

        if (file.length() == 0) {
            System.out.println("如果文件大小等于0,说明第一次使用,存入Access_token");
           // access_token_obj = WeixinUtil.getAccessToken();
            String token = WeixinUtil.getAccessToken();
            FileOutputStream fos = new FileOutputStream("D:/weixin/weixinAccess_token.txt", false);// 不允许追加
            AccessToken at = new AccessToken();
            at.setToken(token);
            at.setExpiresIn(Integer.valueOf(System.currentTimeMillis()/1000+""));
            System.out.println("at"+at);
            mAccess_token=token;
            String json = gson.toJson(at);
            fos.write(json.getBytes());
            fos.close();
        } else {
            System.out.println("读取文件内容");
            // 读取文件内容
            FileInputStream fis = new FileInputStream(file);
            byte[] b = new byte[2048];
            int len = fis.read(b);
            String mJsonAccess_token = new String(b, 0, len);// 读取到的文件内容
            System.out.println("读取到的文件内容"+mJsonAccess_token);
            AccessToken access_token = gson.fromJson(mJsonAccess_token, new AccessToken().getClass());
            if (access_token.getExpiresIn() != null) {
                System.out.println("access_token.getExpiresIn()"+access_token.getExpiresIn());

                long lastSaveTime = access_token.getExpiresIn();
                long nowTime = System.currentTimeMillis()/1000;
                long remianTime = nowTime - lastSaveTime;
             
                System.out.println("lastSaveTime"+lastSaveTime);
                System.out.println("nowTime"+nowTime);
                System.out.println("remianTime"+remianTime);
                System.out.println(remianTime < MAX_TIME);
                if (remianTime < MAX_TIME) {

                    AccessToken access = gson.fromJson(mJsonAccess_token, new AccessToken().getClass());
                    mAccess_token = access.getToken();
                    System.out.println("读取的mAccess_token"+mAccess_token);
                } else {
                    System.out.println("更新mJsonAccess_token");
                   // access_token_obj = WeiXinUtil.getToken();
                    FileOutputStream fos = new FileOutputStream(file, false);// 不允许追加
                    AccessToken newToken = new AccessToken();
                    String token=WeixinUtil.getAccessToken();
                    newToken.setToken(token);
                    newToken.setExpiresIn(Integer.valueOf(System.currentTimeMillis()/1000+""));
                    mAccess_token=token;
                    String json = gson.toJson(newToken);
                    fos.write((json).getBytes());
                    fos.close();
                }
            }
        }
        System.out.println("返回的mAccess_token"+mAccess_token);
        return mAccess_token;
    }

    /**
     * 获取JsApiTicket 保存并且只保存2小时JsApiTicket。如果超过两个小时重新获取;如果没有超过两个小时,直接获取
     * 思路:将获取到的JsApiTicket和当前时间存储到file里,
     * 取出时判断当前时间和存储里面的记录的时间的时间差,如果大于MAX_TIME,重新获取,并且将获取到的存储到file替换原来的内容
     * 如果小于MAX_TIME,直接获取。
     */
    public static String getSavedJsApiTicket(String accessToken) throws IOException {
        Gson gson = new Gson();
        String mJsApiTicket = null;// 需要获取的Access_token;
        System.out.println(System.getProperty("user.di"));
        File file = new File("D:/weixin/weixinJsApiTicket.txt");// Access_token保存的位置
        // 如果文件不存在,创建
        if (!file.exists())
            file.createNewFile();
        // 如果文件大小等于0,说明第一次使用,存入Access_token

        if (file.length() == 0) {
            System.out.println("如果文件大小等于0,说明第一次使用,存入JsApiTicket");
            // access_token_obj = WeixinUtil.getAccessToken();
            String aJsApiTicket = WeixinUtil.getJsApiTicket(accessToken);
            FileOutputStream fos = new FileOutputStream("D:/weixin/weixinJsApiTicket.txt", false);// 不允许追加
            AccessToken at = new AccessToken();
            at.setJsApiTicket(aJsApiTicket);
            at.setExpiresIn(Integer.valueOf(System.currentTimeMillis()/1000+""));
            System.out.println("at"+at);
            mJsApiTicket=aJsApiTicket;
            String json = gson.toJson(at);
            fos.write(json.getBytes());
            fos.close();
        } else {
            System.out.println("读取文件内容");
            // 读取文件内容
            FileInputStream fis = new FileInputStream(file);
            byte[] b = new byte[2048];
            int len = fis.read(b);
            String mJsonjsApiTicket = new String(b, 0, len);// 读取到的文件内容
            System.out.println("读取到的文件内容"+mJsonjsApiTicket);
            AccessToken jsApiTicket = gson.fromJson(mJsonjsApiTicket, new AccessToken().getClass());
            if (jsApiTicket.getExpiresIn() != null) {
                System.out.println("access_token.getExpiresIn()"+jsApiTicket.getExpiresIn());

                long lastSaveTime = jsApiTicket.getExpiresIn();
                long nowTime = System.currentTimeMillis()/1000;
                long remianTime = nowTime - lastSaveTime;
              
                System.out.println("lastSaveTime"+lastSaveTime);
                System.out.println("nowTime"+nowTime);
                System.out.println("remianTime"+remianTime);
                System.out.println(remianTime < MAX_TIME);
                if (remianTime < MAX_TIME) {

                    AccessToken access = gson.fromJson(mJsonjsApiTicket, new AccessToken().getClass());
                    mJsApiTicket = access.getJsApiTicket();
                    System.out.println("读取的JsApiTicket"+jsApiTicket);
                } else {
                    System.out.println("更新JsApiTicket");
                    // access_token_obj = WeiXinUtil.getToken();
                    FileOutputStream fos = new FileOutputStream(file, false);// 不允许追加
                    AccessToken newJsApiTicket = new AccessToken();
                    String jsapiTicket=WeixinUtil.getJsApiTicket(accessToken);
                    newJsApiTicket.setJsApiTicket(jsapiTicket);
                    newJsApiTicket.setExpiresIn(Integer.valueOf(System.currentTimeMillis()/1000+""));
                    mJsApiTicket=jsapiTicket;
                    String json = gson.toJson(newJsApiTicket);
                    fos.write((json).getBytes());
                    fos.close();
                }
            }
        }
        System.out.println("返回的JsApiTicket"+mJsApiTicket);
        return mJsApiTicket;
    }

    public static void main(String args[]) throws IOException {
        WxAccessToken.getSavedJsApiTicket(WxAccessToken.getSavedAccessToken());
    }
}

本地缓存我是参考–>其他缓存的连接写的

以上就是java版–微信jssdk 授权config接口注入权限验证配置的参数获取+全局缓存access_token和jsapi_ticket的全部内容,请大家多多关照

上一篇:Senparc.Weixin JSSDK获取signature签名


下一篇:[转]关于微信JSSDK中遇到的“invalid signature”的天坑