赞
踩
最近的开发公众号h5,需要用的微信的扫一扫,不过微信这些功能,需要先通过config接口注入权限验证配置,翻了好多文章才弄出来,下面开始吧
步骤一:绑定域名
步骤二:引入JS文件
这些我就不说了,这些微信官网都有:: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html.
我们直接开始第三步
下面是获取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(); } }
json转map,这个小工具
import net.sf.json.JSONArray; import net.sf.json.JSONObject; import java.util.*; public class MdzwUtils { //json转map,这个小工具是我从网上找的,谢谢作者 public static Map<String, Object> parseJSON2Map(JSONObject json) { Map<String, Object> map = new HashMap<String, Object>(); // 最外层解析 for (Object k : json.keySet()) { Object v = json.get(k); // 如果内层还是数组的话,继续解析 if (v instanceof JSONArray) { List<Map<String, Object>> list = new ArrayList<>(); @SuppressWarnings("unchecked") Iterator<JSONObject> it = ((JSONArray) v).iterator(); while (it.hasNext()) { JSONObject json2 = it.next(); list.add(parseJSON2Map(json2)); } map.put(k.toString(), list); } else { map.put(k.toString(), v); } } return map; } }
获得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缓存起来
我这里用的是本地文件缓存,通过物理磁盘创建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的全部内容,请大家多多关照
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。