1.rquest
import lombok. Data ;
@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. * ;
@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) ) { long currentTimeMillis = System . currentTimeMillis ( ) ; Date now = new Date ( currentTimeMillis) ; Date expiration = new Date ( currentTimeMillis + weatherProperties. getTokenTTL ( ) * 1000L ) ; byte [ ] keyBytes = Base64 . getDecoder ( ) . decode ( weatherProperties. getKey ( ) ) ; PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec ( keyBytes) ; KeyFactory keyFactory = KeyFactory . getInstance ( "EC" ) ; PrivateKey privateKey = keyFactory. generatePrivate ( keySpec) ; JWTSigner signer = JWTSignerUtil . createSigner ( "ES256" , privateKey) ; Map < String , Object > header = new HashMap < > ( ) ; header. put ( "alg" , "ES256" ) ; header. put ( "kid" , weatherProperties. getKeyId ( ) ) ; Map < String , Object > payload = new HashMap < > ( ) ; payload. put ( "iss" , weatherProperties. getTeamId ( ) ) ; payload. put ( "sub" , weatherProperties. getBundleId ( ) ) ; payload. put ( "iat" , now. getTime ( ) / 1000 ) ; payload. put ( "exp" , expiration. getTime ( ) / 1000 ) ; String token = JWTUtil . createToken ( header, payload, signer) ; 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 ;
@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. apptokenTTL: 3600 languageCode: entimezone: Asia / Shanghai domain: https: / / weatherkit. apple. comweatherEndpoint: / api/ v1/ weatheravailabilityEndpoint: / 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 ;
@FeignClient ( name = "weather-service" , url = "${weather.auth.config.domain}" )
public interface IWeatherApi { @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) ;
}