WeixinBaseUtil.java 5.56 KB
package com.server.utils.weixin;

import com.alibaba.fastjson.JSON;
import com.jfinal.weixin.sdk.api.JsTicket;
import com.jfinal.weixin.sdk.api.JsTicketApi;
import com.jfinal.weixin.sdk.kit.ParaMap;
import com.jfinal.weixin.sdk.utils.HttpUtils;
import com.server.utils.weixin.bean.SnsAccessTokenBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Created by 豆腐干Sama on 2018/12/5.
 */
public class WeixinBaseUtil {
    static Logger logger = LoggerFactory.getLogger(WeixinBaseUtil.class);


    //获取微信accesstockenurl
    public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";

    //获取网页access_token
    private static String SNS_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={appid}&secret={secret}&code={code}&grant_type=authorization_code";

    //获取用户信息url
    private static String USER_INFO_URL = "https://api.weixin.qq.com/sns/userinfo";

    private static String JsapiTicketURL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";

    public static Map<String, Object> authorization(String appId, String appSecret, String code) {
        if (StringUtils.hasText(appId) && StringUtils.hasText(appSecret) && StringUtils.hasText(code)) {
            final String queryAccessTokeUrl = SNS_ACCESS_TOKEN_URL.replace("{appid}", appId).replace("{secret}", appSecret).replace("{code}", code);
            RestTemplate restTemplate = new RestTemplate();
            String json = restTemplate.getForObject(queryAccessTokeUrl, String.class);
            SnsAccessTokenBean snsAccessTokenBean = new SnsAccessTokenBean(json);
            String accessToken = snsAccessTokenBean.getAccessToken();
            String openid = snsAccessTokenBean.getOpenid();

            restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
            String userInfoJsonStr = restTemplate.getForObject(USER_INFO_URL + "?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN", String.class);
            Map userInfoResultMap = JSON.parseObject(userInfoJsonStr, Map.class);
            Number errCode = (Number) userInfoResultMap.get("errcode");
            Integer errorCode = (errCode == null ? null : Integer.valueOf(errCode.intValue()));

            if (errorCode == null || errorCode.intValue() == 0) {
                userInfoResultMap.put("wxAccessToken", snsAccessTokenBean.getAccessToken());
                userInfoResultMap.put("wxRefreshToken", snsAccessTokenBean.getRefresh_token());
                return userInfoResultMap;
            }
        } else {
            logger.error("参数有误");
            return null;
        }
        return null;
    }


    /**
     * 获取微信 ticket
     *
     * @param appId
     * @param accesstoken
     * @param url
     * @param redisTemplate
     * @return
     */
    public static String getTicket(String appId, String accesstoken, String url, RedisTemplate redisTemplate) {
        String key = appId + '_' + JsTicketApi.JsApiType.jsapi.name();
        final ParaMap pm = ParaMap.create("access_token", accesstoken).put("type", JsTicketApi.JsApiType.jsapi.name());
        boolean redisTicket = true;
        String json = "";
        if (redisTemplate.hasKey("wx_ticket_" + key)) {
            json = (String) redisTemplate.opsForValue().get("wx_ticket_" + appId);
            if (StringUtils.hasText(json)) {
                redisTicket = false;
            }
        }
        if (redisTicket) {
            json = HttpUtils.get(WeixinBaseUtil.JsapiTicketURL, pm.getData());
        }
        JsTicket jsTicket = new JsTicket(json);
        return jsTicket.getTicket();
    }


    public static Map<String, Object> sign(String jsapi_ticket, String url, String appId) {
        Map<String, Object> ret = new HashMap<String, Object>();
        String nonce_str = UUID.randomUUID().toString();
        String timestamp = Long.toString(System.currentTimeMillis() / 1000);
        String str;
        String signature = "";
        //注意这里参数名必须全部小写,且必须有序
        str = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "&timestamp=" + timestamp + "&url=" + url;
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(str.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        ret.put("appId", appId);
        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;
    }
}