官方文档:https://work.weixin.qq.com/api/doc#90000/90136/90506/获取企业的jsapi_ticket
第一步:生成实体类,json解析时使用
第二步:调用HttpClients获取access_token和jsapi_ticket
第三步:生成签名算法java实现
第四步:ajax动态获取url,存入redis,两小时定时执行一次,更新签名,存入redis
最后会附上代码。
签名报错:
错误一:"errMsg":"invalid signature."
原因:签名错误,建议按如下顺序检查:
1) 确认签名算法正确,可用http://work.weixin.qq.com/api/jsapisign页面工具进行校验。
2) 确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。
3) 确认url是页面完整的url(请在当前页面alert(location.href.split(‘#’)[0])确认),包括’http(s)://‘部分,以及’?’后面的GET参数部分,但不包括’#’hash后面的部分。
4) 确认config中的appid与用来获取jsapi_ticket的corpid一致。
5) 确保一定缓存access_token和jsapi_ticket。
6) 确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去’#’hash部分的链接(可用location.href.split(‘#’)[0]获取,而且需要encodeURIComponent),因为页面一旦分享,企业微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。
错误二:"errMsg":"invalid url domain."
当前页面所在域名与使用的corpid没有绑定
错误三:"errMsg":"config:not match any reliable domain."
原因:可信用域与你获得到的url不符合,查看是否设可信用域,端口号也要保持一致,没域名要申请
package com.qb.keco.common.EnterpriseWechat;
/**
* access_token实体
* @author qb
* @date
*/
public class Access_token {
private String errcode;
private String errmsg;
private String access_token; //access_token
private String expires_in;
public String getErrcode() {
return errcode;
}
public void setErrcode(String errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getExpires_in() {
return expires_in;
}
public void setExpires_in(String expires_in) {
this.expires_in = expires_in;
}
}
package com.qb.keco.common.EnterpriseWechat;
/**
* access_token实体
* @author qb
* @date
*/
public class Jsapi_Ticket {
private String errcode;
private String errmsg;
private String ticket; //access_token
private String expires_in;
public String getErrcode() {
return errcode;
}
public void setErrcode(String errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public String getTicket() {
return ticket;
}
public void setTicket(String ticket) {
this.ticket = ticket;
}
public String getExpires_in() {
return expires_in;
}
public void setExpires_in(String expires_in) {
this.expires_in = expires_in;
}
}
package com.qb.keco.common.EnterpriseWechat;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.google.gson.Gson;
import freemarker.core.ParseException;
public class HttpClientKey {
public static String getAccessToken() throws ClientProtocolException, IOException {
String message=null,ticket_message=null;
Gson gson = new Gson();
Access_token access = null;Jsapi_Ticket ticket = null;
String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ww5614ccf1c02e6d99&corpsecret=aD5gfH65z5FOKQPkBi1UncsVKrqVkBsrBL1fy5QMib8";
HttpHost proxy = new HttpHost("10.22.33.233", 8080);//代理
RequestConfig requestConfig = RequestConfig.custom()
.setProxy(proxy)//代理
.setConnectTimeout(10000).setSocketTimeout(10000).setConnectionRequestTimeout(3000).build();
HttpPost httpPost = new HttpPost(url);// 创建httpPost
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-Type", "application/json");
httpPost.setConfig(requestConfig);
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpResponse response = httpClient.execute(httpPost);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity resEntity = response.getEntity();
try {
message = EntityUtils.toString(resEntity, "utf-8");
access = gson.fromJson(message, Access_token.class);
String turl = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token="+access.getAccess_token();
HttpPost ticket_httpPost = new HttpPost(turl);// 创建httpPost
ticket_httpPost.setHeader("Accept", "application/json");
ticket_httpPost.setHeader("Content-Type", "application/json");
ticket_httpPost.setConfig(requestConfig);
HttpResponse ticket_response = httpClient.execute(ticket_httpPost);
if (ticket_response.getStatusLine().getStatusCode() == 200) {
HttpEntity ticket_resEntity = ticket_response.getEntity();
try {
ticket_message = EntityUtils.toString(ticket_resEntity, "utf-8");
ticket = gson.fromJson(ticket_message, Jsapi_Ticket.class);
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
httpClient.close();
}
System.out.println(ticket_message);
}
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
httpClient.close();
}
System.out.println(message);
} else {
System.out.println("获取企业jsapi_ticket请求失败!");
}
return ticket.getTicket();
}
}
package com.qb.keco.common.EnterpriseWechat;
import java.util.UUID;
import org.apache.http.client.ClientProtocolException;
import java.util.Map;
import java.util.HashMap;
import java.util.Formatter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class MySign {
public static void main(String[] args) throws ClientProtocolException, IOException {
String jsapi_ticket = HttpClientKey.getAccessToken();
String url = "";
Map<String, String> ret = sign(jsapi_ticket, url);
for (Map.Entry entry : ret.entrySet()) {
System.out.println(entry.getKey() + ", " + entry.getValue());
}
};
public static Map<String, String> sign(String jsapi_ticket, String url) {
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);
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;
}
//生成随机字符串
private static String create_nonce_str() {
return UUID.randomUUID().toString();
}
//生成时间戳
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
@Scheduled(fixedRate = 1000*60*118)
public void setMySign() throws ClientProtocolException, IOException {
String jsapi_ticket = HttpClientKey.getAccessToken();
String url = JedisUtils.get("url");
Map<String, String> ret = MySign.sign(jsapi_ticket, url);
JedisUtils.setMap("mysign", ret, 0);
/*Map<String, String> te = JedisUtils.getMap("mysign");
System.out.println("更新后sign:");
for (Map.Entry entry : te.entrySet()) {
System.out.println(entry.getKey() + ", " + entry.getValue());
}*/
}