import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jfb.jfbmanager.wx.controller.IndexController;
import com.jfb.jfbmanager.wx.model.ScanBaseResp;
import org.apache.commons.lang.StringUtils;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
/**
* @description: 签名
* @author: hqh
* @create: 2020-06-27 20:43
**/
public class SignUtil {
private final static Logger logger = LoggerFactory.getLogger(SignUtil.class);
private static Map<String, String> tokens = new HashMap<>();
// private static String token = "";//此处使用的值,需要服务器的配置的token保持一致
/**
* @Description:检查签名
* @Param: [signature, timestamp, nonce]
* @return: boolean
* @Author: hqh
* @Date: 2020/8/10
*/
public static boolean checkSignature(String signature,String timestamp,String nonce){
String checktext = null;
if(null!=signature){
//对token,timestatmp,nonce 按字典排序
String[] paramArr = new String[]{PropertisUtil.token,timestamp,nonce};
Arrays.sort(paramArr);
//将排序后的结果拼成一个字符串
String content = paramArr[0].concat(paramArr[1]).concat(paramArr[2]);
try{
MessageDigest md =MessageDigest.getInstance("SHA-1");
//对接后的字符串i女性sha1加密
byte[] digest = md.digest(content.toString().getBytes());
checktext=byteTostr(digest);
}catch (Exception e){
e.printStackTrace();
}
}
return checktext !=null?checktext.equals(signature.toUpperCase()):false;
}
private static String byteTostr(byte[] byteArrays){
String str = "";
for(int i=0;i<byteArrays.length;i++)
{
str += byteToHexStr(byteArrays[i]);
}
return str;
}
private static String byteToHexStr(byte myByte){
char[] Digit = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char[] tampArr = new char[2];
tampArr[0] = Digit[(myByte >>>4 )& 0X0F];
tampArr[1] = Digit[myByte & 0X0F];
String str = new String(tampArr);
return str;
}
/**
* 获取sign签名
*
* @return
*/
public static Map sign(HttpServletRequest request, HttpServletResponse response) {
Map ret = new HashMap();
String url = request.getParameter("url");
String jsapi_ticket = JsApiTicketUtils.getJsApiTicket().get("jsapi_ticket");
String nonce_str = create_nonce_str();
String timestamp = create_timestamp();
String string1="";
String signature = "";
int length = url.indexOf("#");
String uri = url;
if (length > 0) {
uri = url.substring(0, length);// 当前网页的URL,不包含#及其后面部分
}
// 注意顺序
string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url=" + url;
logger.info(">>>>>>>签名字符串:" + 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("appId",PropertisUtil.appid);
ret.put("url", uri);
ret.put("jsapi_ticket", jsapi_ticket);
ret.put("nonceStr", nonce_str);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
logger.info(">>>>>>>>>>签名:"+signature);
logger.info("获取sign结果:" + JSON.toJSONString(ret));
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);
}
/**
* 根据code 获取用户openID
*/
public static ScanBaseResp getUserOpenId(String code) {
ScanBaseResp resp = new ScanBaseResp();
String requestUrl = PropertisUtil.access_token_oauth2_url;
String params = "?appid=" + PropertisUtil.appid+ "&secret=" + PropertisUtil.appsecret+ "&code=" + code
+ "&grant_type=authorization_code";
logger.info(">>>>>>>>>>>请求url字符串:"+requestUrl+params);
String result = httpGet(requestUrl + params);
logger.info("获取当前用户信息:" + JSON.toJSONString(result));
String openid = JSONObject.parseObject(result).getString("openid");
logger.info(">>>>>>>openId:"+openid);
resp.setMsg(openid);// 当前用户openid
return resp;
}
/**
* 发送get请求
*
* @param url
* 路径
* @return
*/
public static String httpGet(String url) {
String strResult = null;
try {
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request);
if (response.getStatusLine().getStatusCode() == org.apache.http.HttpStatus.SC_OK) {
strResult = EntityUtils.toString(response.getEntity());
} else {
logger.info("get请求提交失败:" + url);
}
} catch (IOException e) {
e.printStackTrace();
logger.info("请求异常:" + e.getMessage());
}
return strResult;
}
public static String getWxToken() {
String token = tokens.get("token");
String time = tokens.get("time");
Long nowDate = new Date().getTime();
if ( StringUtils.isNotBlank(token)&& StringUtils.isNotEmpty(token) && StringUtils.isNotBlank(time)&&StringUtils.isNotEmpty(time) && nowDate - Long.parseLong(time) < (1.5*60*60*1000)) {
return token;
}
synchronized (SignUtil.class) {
if(StringUtils.isNotBlank(token)&& StringUtils.isNotEmpty(token) && StringUtils.isNotBlank(time)&&StringUtils.isNotEmpty(time) && nowDate - Long.parseLong(time) < (1.5*60*60*1000)) {
return token;
}
//log.info("jsApiTicket超时,或者不存在,重新获取");
try {
// 当过期时间超过两小时,则重新获取新的access_token
String requestUrl = PropertisUtil.token_url;
String params = "?grant_type=client_credential&appid=" + PropertisUtil.appid+ "&secret=" + PropertisUtil.appsecret;
String result = httpGet(requestUrl + params);
logger.info("################获取微信token结果:" + JSON.toJSONString(result));
token = JSONObject.parseObject(result).getString("access_token");
tokens.put("time", nowDate + "");
tokens.put("token", token);
} catch (Exception e) {
e.printStackTrace();
}
return token;
}
}
/**
* jsapi_ticket是公众号用于调用微信JS接口的临时票据
* */
public static String getJsApiTicket(String accessToken, String type){
String jsApiTicket = "";
// 这个url链接地址和参数皆不能变
String url = PropertisUtil.getticket_url+"?access_token="+accessToken+"&type="+type;
try {
JSONObject jsonObject = WeiXinUtil.httpRequest(url, "GET", null);
logger.info("获取jsapi_ticket返回的json:"+jsonObject);
Long expiresIn = jsonObject.getLong("expires_in");
logger.info("微信获取的expires_in:"+expiresIn);
jsApiTicket = jsonObject.getString("ticket");
logger.info("微信获取的ticket:"+jsApiTicket);
}catch (Exception e){
logger.debug("获取jsapi_ticket发生异常",e);
}
return jsApiTicket;
}
}