package com.bigfat.coolweather.util; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Calendar; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; /** * @author <a href="mailto:fbzhh007@gmail.com">bigfat</a> * @since 2014/12/17 */ public class WeatherApiUtil { private static final char last2byte = (char) Integer.parseInt("00000011", 2); private static final char last4byte = (char) Integer.parseInt("00001111", 2); private static final char last6byte = (char) Integer.parseInt("00111111", 2); private static final char lead6byte = (char) Integer.parseInt("11111100", 2); private static final char lead4byte = (char) Integer.parseInt("11110000", 2); private static final char lead2byte = (char) Integer.parseInt("11000000", 2); private static final char[] encodeTable = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; /** * 获取气象数据开放平台请求url * * @param areaid 地区码 * @param type 获取气象数据类型 * @return 气象数据开放平台请求url */ public static String getWeatherUrl(String areaid, String type) { String public_key = getWeatherPublicKey(areaid, type); StringBuilder sb = new StringBuilder(); sb.append(public_key.substring(0, public_key.length() - 10)); sb.append("&key="); sb.append(standardURLEncoder(public_key)); return sb.toString(); } /** * 根据气象编号获取气象中文名称 * * @param weatherId 气象编号 * @return 气象中文名称 */ public static String getWeatherById(String weatherId) { switch (weatherId) { case "00": return "晴"; case "01": return "多云"; case "02": return "阴"; case "03": return "阵雨"; case "04": return "雷阵雨"; case "05": return "雷阵雨伴有冰雹"; case "06": return "雨夹雪"; case "07": return "小雨"; case "08": return "中雨"; case "09": return "大雨"; case "10": return "暴雨"; case "11": return "大暴雨"; default: return ""; } } /** * 获取当前时间:yyyyMMddHHmm * * @return String */ private static String getDate4yyyyMMddHHmm() { Calendar c = Calendar.getInstance(); String year = String.valueOf(c.get(Calendar.YEAR)); String month = String.valueOf(c.get(Calendar.MONTH) + 1); String day = String.valueOf(c.get(Calendar.DAY_OF_MONTH)); String hour = String.valueOf(c.get(Calendar.HOUR_OF_DAY)); String mins = String.valueOf(c.get(Calendar.MINUTE)); // String secs = String.valueOf(c.get(Calendar.SECOND)); return year + month + day + hour + mins; } /** * 拼接气象数据开放平台public_key,用于生成秘钥 * * @param areaid 地区码 * @param type 获取气象数据类型 * @return 气象数据开放平台public_key */ public static String getWeatherPublicKey(String areaid, String type) { StringBuilder sb = new StringBuilder(); sb.append(Constant.WEATHER_API); sb.append("areaid="); sb.append(areaid); sb.append("&type="); sb.append(type); sb.append("&date="); sb.append(getDate4yyyyMMddHHmm()); sb.append("&appid="); sb.append(Constant.WEATHER_APPID); return sb.toString(); } /** * 计算气象数据开放平台传参key(令牌) * * @param public_key 明文(public_key) * @return 令牌 */ public static String standardURLEncoder(String public_key) { byte[] byteHMAC = null; String urlEncoder = ""; try { Mac mac = Mac.getInstance("HmacSHA1"); SecretKeySpec spec = new SecretKeySpec(Constant.WEATHER_PRIVATE_KEY.getBytes(), "HmacSHA1"); mac.init(spec); byteHMAC = mac.doFinal(public_key.getBytes()); if (byteHMAC != null) { String oauth = encode(byteHMAC); if (oauth != null) { urlEncoder = URLEncoder.encode(oauth, "utf8"); } } } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) { e.printStackTrace(); } return urlEncoder; } public static String encode(byte[] from) { StringBuffer to = new StringBuffer((int) (from.length * 1.34) + 3); int num = 0; char currentByte = 0; for (int i = 0; i < from.length; i++) { num = num % 8; while (num < 8) { switch (num) { case 0: currentByte = (char) (from[i] & lead6byte); currentByte = (char) (currentByte >>> 2); break; case 2: currentByte = (char) (from[i] & last6byte); break; case 4: currentByte = (char) (from[i] & last4byte); currentByte = (char) (currentByte << 2); if ((i + 1) < from.length) { currentByte |= (from[i + 1] & lead2byte) >>> 6; } break; case 6: currentByte = (char) (from[i] & last2byte); currentByte = (char) (currentByte << 4); if ((i + 1) < from.length) { currentByte |= (from[i + 1] & lead4byte) >>> 4; } break; } to.append(encodeTable[currentByte]); num += 6; } } if (to.length() % 4 != 0) { for (int i = 4 - to.length() % 4; i > 0; i--) { to.append("="); } } return to.toString(); } }