在上一篇文章中介绍了微信自定义分享对页面进行的配置。想要实现页面的这些配置,需要后台获取相应的值传到页面中。
那么那些值都是如何获取的呢?
如需获取页面中的值,APPID是公众号的唯一标识(存储在数据库中),可通过accountID(公众号id)来得到。timestamp ,生成签名的时间戳和nonceStr签名生成的字符串可以这样获取:
private static String create_nonce_str() {
return UUID.randomUUID().toString();//随机字符串
}
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);//时间戳
}
签名机制:
1、通过access_token采用http Get方式的请求获取jsapi_ticket(有效期为7200秒)
2、通过得到的jsapi_ticket和随机字符串noncestr,时间戳timestamp,当前网页的URL(不包含#及其后面部分),对这几个参数按照ASCII码从小到大排序(字典序),使用URL键值对的格式(key1=value1&key2=value2…)拼接成字符串string1,这里所有的参数均为小写字符。
3、然后对string1进行SHA1加密。字段名和字段值都采用原始值,不进行URL转义。
public Map test(HttpServletRequest requesturl, String accountid) throws Exception {
String ticket = getWeiXinTicket(accountid);
// 注意 URL 一定要动态获取,不能 hardcode
String url = requesturl.getRequestURL().toString();
String domain = ResourceUtil.getConfigByName("domain");
String param = requesturl.getQueryString();
url = url + "?" + param;
Map ret = sign(ticket, url);
for (Map.Entry entry : ret.entrySet()) {
System.out.println(entry.getKey() + ", " + entry.getValue());
}
ret.put("appId", appId);
return ret;
}
public static Map sign(String jsapi_ticket, String url) {
Map ret = new HashMap();
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);
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);
return ret;
}
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;
}
public String getWeiXinTicket(String accountid) throws Exception {
String token = getAccessToken(accountid);
// if(null==apiticket){
// URL url1=new URL("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+accessToken.getToken()+"&type=jsapi");
// String urll = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=accessToken&type=jsapi";
String urll = WeixinUtil.share_url;
String requestUrll = urll.replace("accessToken", token);
JSONObject json1 = httpRequest(requestUrll, "GET", null);
String ticket = (String) json1.get("ticket");
return ticket;
// 断开连接
}
public String getAccessToken(String accountId) throws Exception {
String token = "";
// WeixinAccountServiceImpl impl=new WeixinAccountServiceImpl();
WeixinAccountEntity account = weixinAccountService.findUniqueByProperty(WeixinAccountEntity.class, "id", accountId);
appId = account.getAccountappid();
if (!account.getAuthorizationType().equalsIgnoreCase("0")) {
return this.getAuthorizerAccessToken(account.getId());
}
token = account.getAccountaccesstoken();
if (token != null && !"".equals(token)) {
// 判断有效时间 是否超过2小时
java.util.Date end = new java.util.Date();
java.util.Date start = new java.util.Date(account.getAddtoekntime()
.getTime());
if ((end.getTime() - start.getTime()) / 1000 / 3600 >= 2) {
// 失效 重新获取
String requestUrl = WeixinUtil.access_token_url.replace(
"APPID", account.getAccountappid()).replace(
"APPSECRET", account.getAccountappsecret());
JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl,
"GET", null);
if (null != jsonObject) {
try {
token = jsonObject.getString("access_token");
// 重置token
account.setAccountaccesstoken(token);
// 重置事件
account.setAddtoekntime(new Date());
weixinAccountService.saveOrUpdate(account);
} catch (Exception e) {
token = null;
// 获取token失败
String wrongMessage = "获取token失败 errcode:{} errmsg:{}"
+ jsonObject.getInt("errcode")
+ jsonObject.getString("errmsg");
}
}
} else {
return account.getAccountaccesstoken();
}
} else {
String requestUrl = WeixinUtil.access_token_url.replace("APPID",
account.getAccountappid()).replace("APPSECRET",
account.getAccountappsecret());
JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "GET",
null);
if (null != jsonObject) {
try {
token = jsonObject.getString("access_token");
// 重置token
account.setAccountaccesstoken(token);
// 重置事件
account.setAddtoekntime(new Date());
weixinAccountService.saveOrUpdate(account);
} catch (Exception e) {
token = null;
// 获取token失败
String wrongMessage = "获取token失败 errcode:{} errmsg:{}"
+ jsonObject.getInt("errcode")
+ jsonObject.getString("errmsg");
}
}
}
return token;
}
public String getWeiXinTicket(String accountid) throws Exception {
WeixinAccountEntity account = weixinAccountService.findUniqueByProperty(WeixinAccountEntity.class, "id", accountid);
String ticket="";
ticket=account.getJsapiTicket();
if (ticket != null && !"".equals(ticket)) {
// 判断有效时间 是否超过2小时
java.util.Date end = new java.util.Date();
java.util.Date start = new java.util.Date(account.getJsapiTicketTime()
.getTime());
if ((end.getTime() - start.getTime()) / 1000 / 3600 >= 2) {
// 失效 重新获取
String urll = WeixinUtil.share_url;
String token = getAccessToken(accountid);
String requestUrll = urll.replace("accessToken", token);
JSONObject json1 = httpRequest(requestUrll, "GET", null);
if (null != json1) {
try {
ticket = (String) json1.get("ticket");
// 重置ticket
account.setJsapiTicket(ticket);
// 重置事件
account.setJsapiTicketTime(new Date());
weixinAccountService.saveOrUpdate(account);
} catch (Exception e) {
token = null;
// 获取token失败
String wrongMessage = "获取ticket失败 errcode:{} errmsg:{}"
+ json1.getInt("errcode")
+ json1.getString("errmsg");
}
}
} else {
ticket= account.getJsapiTicket();
}
} else {
String urll = WeixinUtil.share_url;
String token = getAccessToken(accountid);
String requestUrll = urll.replace("accessToken", token);
JSONObject json1 = httpRequest(requestUrll, "GET", null);
if (null != json1) {
try {
ticket = (String) json1.get("ticket");
// 重置ticket
account.setJsapiTicket(ticket);
// 重置事件
account.setJsapiTicketTime(new Date());
weixinAccountService.saveOrUpdate(account);
} catch (Exception e) {
token = null;
// 获取token失败
String wrongMessage = "获取ticket失败 errcode:{} errmsg:{}"
+ json1.getInt("errcode")
+ json1.getString("errmsg");
}
}
}
public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = {new MyX509TrustManager()};
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
jsonObject = JSONObject.fromObject(buffer.toString());
// jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
org.jeecgframework.core.util.LogUtil.info("Weixin server connection timed out.");
} catch (Exception e) {
org.jeecgframework.core.util.LogUtil.info("https request error:{}" + e.getMessage());
}
return jsonObject;
}
public String getAuthorizerAccessToken(String id) {
String ret = "";
if (StringUtils.isBlank(id)) {
return ret;
}
WeixinAccountEntity account = weixinAccountService.findUniqueByProperty(WeixinAccountEntity.class, "id", id);
// WeixinAccountEntity account = this.getEntity(WeixinAccountEntity.class, id);
if (account.getAuthorizationType().equalsIgnoreCase("0")) {
logger.info(String.format("weixin account %s 没有使用第三方授权", id));
} else {
String token = account.getAuthorizerAccessToken();
if (StringUtils.isNotBlank(token) && account.getAuthorizerAccessTokenExpireTime().after(new Date())) {
ret = token;
} else {
String platformId = account.getOpenPlatformId();
WeixinOpenPlatformEntity platform = weixinOpenPlatformService.getEntity(WeixinOpenPlatformEntity.class, platformId);
String componentAccessToken = getComponentAccessToken(id);
String componentAppId = platform.getAppId();
String authorizerAppId = account.getAccountappid();
String refreshToken = account.getAuthorizerRefreshToken();
String requestUrl = API_AUTHORIZER_TOKEN.replace("COMPONENT_ACCESS_TOKEN", componentAccessToken);
JSONObject postData = new JSONObject();
postData.put("component_appid", componentAppId);
postData.put("authorizer_appid", authorizerAppId);
postData.put("authorizer_refresh_token", refreshToken);
JSONObject obj = WeixinUtil.httpRequest(requestUrl, "POST", postData.toString());
if (obj.containsKey("authorizer_access_token")) {
String authorizerAccessToken = obj.getString("authorizer_access_token");
String authorizerRefreshToken = obj.getString("authorizer_refresh_token");
int expiresIn = obj.getInt("expires_in");
Date expireTime = addTime(new Date(), expiresIn, Calendar.SECOND);
ret = authorizerAccessToken;
account.setAuthorizerAccessToken(authorizerAccessToken);
account.setAuthorizerRefreshToken(authorizerRefreshToken);
account.setAuthorizerAccessTokenExpireTime(expireTime);
weixinAccountService.saveOrUpdate(account);
} else {
logger.info(String.format("获取authorizer_access_token失败: %s", obj.toString()));
}
}
}
return ret;
}
public String getComponentAccessToken(String id) {
String ret = "";
WeixinAccountEntity account = weixinAccountService.findUniqueByProperty(WeixinAccountEntity.class, "id", id);
if (account.getId().equalsIgnoreCase("-1")) {
logger.info("找不到当前登录微信公众号");
return ret;
} else {
if (account.getAuthorizationType().equalsIgnoreCase("1") || account.getAuthorizationType().equalsIgnoreCase("2")) {
String platformId = account.getOpenPlatformId();
ret = this.getComponentAccessToken(platformId, "temp");
} else {
logger.info(String.format("公众号未采用第三方授权. id:%s, authorizationType:%s, accountId:%s", account.getId(), account.getAuthorizationType(), account.getWeixin_accountid()));
}
}
return ret;
}
public String getComponentAccessToken(String platformId, String temp) {
String ret = "";
if (StringUtils.isBlank(platformId)) {
return ret;
}
WeixinOpenPlatformEntity entity = systemService.get(WeixinOpenPlatformEntity.class, platformId);
Date now = new Date();
if (StringUtils.isNotBlank(entity.getComponentAccessToken()) && entity.getTokenExpireTime().after(now)) {
ret = entity.getComponentAccessToken();
} else {
JSONObject postData = new JSONObject();
postData.put("component_appid", entity.getAppId());
postData.put("component_appsecret", entity.getAppSecret());
postData.put("component_verify_ticket", entity.getComponentVerifyTicket());
JSONObject obj = WeixinUtil.httpRequest(API_COMPONENT_TOKEN, "POST", postData.toString());
if (obj.containsKey("component_access_token")) {
String token = obj.getString("component_access_token");
Integer expiresIn = obj.getInt("expires_in");
ret = token;
Date expireTime = addTime(new Date(), expiresIn, Calendar.SECOND);
entity.setComponentAccessToken(token);
entity.setTokenExpireTime(expireTime);
systemService.save(entity);
} else {
logger.info(String.format("获取component_access_token失败. %s", obj.toString()));
}
}
return ret;
}
private Date addTime(Date current, int value, int unit) {
Calendar c = Calendar.getInstance();
c.setTime(current);
c.add(unit, value);
return c.getTime();
}