当前位置: 首页 > article >正文

第三方接口-苹果-获取天气接口

1.rquest


import lombok.Data;

/**

 * @version 1.0
 * @description: 天气
 * @date 2024/9/12 15:18
 */
@Data
public class WeatherRequest {

    /**
     * 语言
     */
    private String lang;
    /**
     * 经度
     */
    private String lat;
    /**
     * 纬度
     */
    private String lon;
    /**
     * 城市
     */
    private String city;
}

2.Controller



import com.engwe.app.api.request.weather.WeatherRequest;
import com.engwe.app.trigger.controller.http.weather.service.WeatherService;
import com.engwe.common.frame.types.dto.R;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Map;

@RestController
@RequestMapping("/api/app/weather")
@Validated
public class WeatherController {

    @Resource
    private WeatherService weatherService;

    @PostMapping("/index")
    public R<Map<String, Object>> index(@RequestBody @Valid WeatherRequest request) {
        return R.ok(weatherService.weather(request));
    }
}

3 service

package com.engwe.app.trigger.controller.http.weather.service;

import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.engwe.app.api.IWeatherApi;
import com.engwe.app.api.request.weather.WeatherRequest;
import com.engwe.app.trigger.controller.http.weather.properties.WeatherProperties;
import com.engwe.common.redis.utils.RedisUtils;
import com.engwe.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Duration;
import java.util.*;

/**
 * 天气服务
 *
 * @link https://developer.apple.com/documentation/weatherkitrestapi/get-api-v1-weather-_language_-_latitude_-_longitude_
 */
@Slf4j
@Service
public class WeatherService {

    @Resource
    private WeatherProperties weatherProperties;

    @Resource
    private IWeatherApi weatherApi;


    public Map<String, Object> weather(WeatherRequest request) {
        try {
            String cityWeatherCacheKey = StringUtils.joinWith(":", "weather", request.getCity());
            Map<String, Object> cacheObject = getWeatherFromCache(cityWeatherCacheKey);
            if (Objects.nonNull(cacheObject) && !cacheObject.isEmpty()) {
                return cacheObject;
            }
            String token = getToken();
            Map<String, String> requestParams = new HashMap<>();
            requestParams.put("countryCode", request.getCity());
            requestParams.put("dataSets", "currentWeather,forecastHourly");
            cacheObject = weatherApi.getWeatherByLocation("Bearer " + token, request.getLang(), request.getLat(), request.getLon(), requestParams);
            RedisUtils.setCacheObject(cityWeatherCacheKey, cacheObject, Duration.ofSeconds(weatherProperties.getTokenTTL() - 60));
            return cacheObject;
        } catch (Exception e) {
            log.error("get weather info error", e);
            return null;
        }
    }

    private Map<String, Object> getWeatherFromCache(String cityWeatherCacheKey) {
        Object cacheObject = RedisUtils.getCacheObject(cityWeatherCacheKey);
        return Objects.nonNull(cacheObject) ? (Map<String, Object>) cacheObject : null;
    }

    private String getToken() throws Exception {
        final String cacheKey = StringUtils.joinWith(":", "weather", "token");
        Object cacheObject = RedisUtils.getCacheObject(cacheKey);
        if (Objects.isNull(cacheObject)) {

            // Define JWT claims
            long currentTimeMillis = System.currentTimeMillis();
            Date now = new Date(currentTimeMillis);
            Date expiration = new Date(currentTimeMillis + weatherProperties.getTokenTTL() * 1000L); // 1-hour expiration


            byte[] keyBytes = Base64.getDecoder().decode(weatherProperties.getKey());
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("EC");  // Apple uses EC (Elliptic Curve) algorithm
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            JWTSigner signer = JWTSignerUtil.createSigner("ES256", privateKey);


            Map<String, Object> header = new HashMap<>();
            header.put("alg", "ES256"); // Algorithm used for signing
            header.put("kid", weatherProperties.getKeyId());  // Key ID

            Map<String, Object> payload = new HashMap<>();
            payload.put("iss", weatherProperties.getTeamId());    // Team ID
            payload.put("sub", weatherProperties.getBundleId());  // Issuer ID
            payload.put("iat", now.getTime() / 1000); // Issued at time in seconds
            payload.put("exp", expiration.getTime() / 1000); // Expiration time in seconds

            String token = JWTUtil.createToken(header, payload, signer);

            // 提前60s过期
            RedisUtils.setCacheObject(cacheKey, token, Duration.ofSeconds(weatherProperties.getTokenTTL() - 60));
            return token;
        }

        return (String) cacheObject;
    }


}

4.WeatherProperties

package com.engwe.app.trigger.controller.http.weather.properties;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**

 * @version 1.0
 * @description:
 * @date 2024/9/11 9:20
 */
@Component
@ConfigurationProperties(prefix = "weather.auth.config")
@Getter
@Setter
public class WeatherProperties {

    private String key;

    private String keyId;

    private String teamId;

    private String bundleId;

    /**
     * 单位秒
     */
    private Integer tokenTTL;

    private String languageCode;

    private String timezone;

    private String weatherEndpoint;

    private String availabilityEndpoint;

}

5.nacos配置

拥有自己的苹果账号去苹果第三方的那个网址获取key这些东西

weather:
  auth:
    config:
      key: MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgHtq+c5C71dUVFQc5RWHzRRxjRqmnxpQ45pMakniZ2uugCgYIKoZIzj0DAQehRANCAAQkGzFLpI+WYcI13yunuPu1qQHBospCyVlxKaWKomCNli9ncA3HFr65qccqwk11AUPIetd5K0hh4MoNANRE94hH
      keyId: JC75LXPCZ5
      teamId: M8PTMPM89H
      bundleId: com.engwe.app
      tokenTTL: 3600
      languageCode: en
      timezone: Asia/Shanghai
      domain: https://weatherkit.apple.com
      weatherEndpoint: /api/v1/weather
      availabilityEndpoint: /api/v1/availability

6 IWeatherApi


import feign.Headers;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.Map;

/**
 * @author luxin@engwebikes.cn
 * @version 1.0
 * @description: TODO
 * @date 2024/9/12 15:26
 */
@FeignClient(name = "weather-service", url = "${weather.auth.config.domain}")
public interface IWeatherApi {

//    @GetMapping("/api/v1/weather/{lang}/{lat}/{lon}")
    @GetMapping("${weather.auth.config.weatherEndpoint}/{lang}/{lat}/{lon}")
    Map<String, Object> getWeatherByLocation(@RequestHeader("Authorization") String token, @PathVariable("lang") String lang, @PathVariable("lat") String lat, @PathVariable("lon") String lon, @RequestParam Map<String, String> params);
}


http://www.kler.cn/news/312019.html

相关文章:

  • Flask、Werkzeug 和 WSGI 间的关系
  • 代码随想录算法训练营第三十二天 | 509. 斐波那契数,70. 爬楼梯,746. 使用最小花费爬楼梯
  • PHP 实现 redis 分布式锁
  • 中间件安全(二)
  • 作品集生成链接或二维码:设计师求职
  • 数据结构和算法之线性结构
  • Java中Integer的缓存池是怎么实现的?
  • 旧系统迁移新框架:FastAPI 的 WSGIMiddleware 让过程变得简单
  • 松材线虫无人机数据集——20731个,已人工标注出来的样本【深度学习样本】
  • 【Leetcode:2848. 与车相交的点 + 模拟计数】
  • Java | Leetcode Java题解之第413题等差数列划分
  • 最新!综合性SCI期刊汇总!《NATURE》位居榜首~
  • 大数据基础架构技术栈一览
  • Redis 的三个并发问题及解决方案(面试题)
  • 【AI大模型】ChatGPT模型原理介绍(下)
  • Redis 执行 Lua,能保证原子性吗?
  • 深入解析 JVM 中静态块、静态属性、构造块与构造方法的执行顺序
  • Vue2项目升级攻略:如何更新package.json中的依赖
  • WPF 中的线程池
  • 阿里云盘照片事件!网络安全警钟长鸣
  • 网站采用H5+CSS3开发的优势和劣势
  • postgresql-patroni高可用安装部署
  • 中国电子学会202306青少年软件编程(Python)等级考试试卷(二级)真题
  • Kubernetes调度基础
  • 二叉树的遍历【C++】
  • python批量对遥感影像进行归一化与数据清洗
  • 【Linux】—— muduo网络库的安装配置与使用
  • 第160天:安全开发-Python-蓝队项目流量攻击分析文件动态监控Webshell检测
  • DepthCrafter:为开放世界视频生成一致的长深度序列
  • VISIA 皮肤检测