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的全部内容,请大家多多关照