2025-11-21 和风天气api开发日志
一、注册账号
和风天气官网:https://www.qweather.com/

开发文档:https://dev.qweather.com/

没账号的话先去注册

我已经有账号了,就不演示了,待会注册完账号就直接登录吧
二:创建项目

三、进入项目、点击创建凭据,创建公私钥

参考文档,当创建前需要先进行身份认证,身份认证我选择的是JWT类型,添加JWT凭据,需要先创建Ed25519公钥和私钥。也就是说你得在你的服务器生成密钥文件,把密钥文件复制到凭据名称里面

官方说明:https://dev.qweather.com/docs/configuration/project-and-key/

生成密钥

我是怎么做的,刚开始我是在我的Linux服务器里面生成的,如果你使用的官方推荐的命令:
openssl genpkey -algorithm ED25519 -out ed25519-private.pem \ && openssl pkey -pubout -in ed25519-private.pem > ed25519-public.pem
可能会遇到报错:
[root@VM-220-19-centos ~]# openssl genpkey -algorithm ED25519 -out ed25519-private.pem \ > && openssl pkey -pubout -in ed25519-private.pem > ed25519-public.pem Algorithm ED25519 not found [root@VM-220-19-centos ~]# openssl version OpenSSL 1.0.2k-fips 26 Jan 2017
上面我还打印了openssl的版本号,可知是服务器的openssl版本需要升级了,版本低会导致不支持 ED25519 算法
后来我想了下,并不需要使用Linux服务器,本地window电脑也能生成呀!只要装了openssl这个工具,比如git工具就完全支持呀!!
重新来!右键点击Git Bash Here

然后输入openssl查看版本
openssl -version
很好,版本没问题(参考资料:ED25519 是在 OpenSSL 1.1.1 版本中才正式加入支持的(发布于 2018 年 9 月))
输入官方给的代码,回车!

很好!得到了公私密钥!!

使用任意文本编辑器打开公钥文件(比如刚才创建的ed25519-public.pem),复制其中的全部内容

很好!保存成功!这样就成功一半了!

可以不看:
身份认证用的是API KEY,你创建完凭据、公私钥这些东西它就会给你一个api key,你拿这个key就能去获取token,但官网目前推荐使用jwt来获取,我以前也没接触过这个和风天气,那么我用的也就是jwt来生成token,不过这里坑还是有点多的。。。

嗯。。。下面说一下怎么调用这个和风天气的api吧
四:如何开发(NestJs方向)
首先,你做到这里,至少有了以下配置:
项目id、凭据id、私钥
1.生成JWT

jwt的内容分为3个部分:Header,Payload和Signature。
1.1、Header组成:
{ "alg": "EdDSA", "kid": "凭据id" }
注意:alg的值是写死的,上面那个示例需要是json格式,这2个值配置完后把这个json对象用base64url进行编码
最终得到(示例):eyJhbGciOiJFZERTQSIsImtpZCI6IkM1Qj123MjJUREoiLCJ0eXAiOiJKV1QifQ
1.2、Payload组成:
{ "sub": "凭据的项目id", "iat": 1703912400, "exp": 1703912940 }
官方文档说明:
sub签发主体,这个值是凭据的项目IDiat签发时间,这个值表示JWT签发生效的时间,UNIX时间戳格式。为了防止时间误差,建议你将iat设置为当前时间之前的30秒,并确保你的服务器或设备的时间和日期是正确的。exp过期时间,这个值表示JWT在何时过期,UNIX时间戳格式。较长的过期时间可以减轻负载,但是较短的时间可以提高安全性。你应该根据使用场景设置过期时间,例如在服务端,可能适合较长的时间,在前端则适合较短的时间。目前允许的有效期最长为24小时(86400秒)。
注意:这里有个坑,就是两时间的时区一定得对上,比如你现在在本地开发,生成的时间,时区要和你本地的时间对上,不然就会出现我遇到一种情况:exp即过期时间是我电脑时间的几个小时前...
这3个值配置完后把这个json对象用base64url进行编码
最终得到(示例):eyJzdWIiOiIyQTJGSk5USkY5IiwiaWF0Ijo123YzNzk5ODU3LCJleHAiOjE3NjM4MDE2NTd9
1.3、Signature组成:
官方文档:将Header和Payload分别进行Base64URL编码并用英文句号拼接在一起,使用你的私钥对其进行Ed25519算法的签名,之后对签名结果同样进行Base64URL编码。
注意:必须使用Base64URL编码,而不是Base64,两者有些许差别。
拿上面的来举例,你已经有了Header、Payload,也就是eyJhbGciOiJFZERTQSIsImtpZCI6IkM1Qj123MjJUREoiLCJ0eXAiOiJKV1QifQ和eyJzdWIiOiIyQTJGSk5USkY5IiwiaWF0Ijo123YzNzk5ODU3LCJleHAiOjE3NjM4MDE2NTd9,把它俩用逗号连起来:
eyJhbGciOiJFZERTQSIsImtpZCI6IkM1Qj123MjJUREoiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiIyQTJGSk5USkY5IiwiaWF0Ijo123YzNzk5ODU3LCJleHAiOjE3NjM4MDE2NTd9
这样能理解吧,,,,好!拿出你的私钥,关键点在于使用你的私钥对其进行Ed25519算法的签名
步骤如下:
由于我用的是nestjs来作为后端开发框架,我这里使用的是crypto这个库来做签名
const signature = crypto.sign(algorithm, data, privateKey);
签名 = crypto.sign(算法, 数据, 私钥);
代码片段如下:
const crypto = require('crypto'); // 1. 准备私钥 const privateKeyPem = `-----BEGIN PRIVATE KEY----- MC4CAQAwBQYDK2VwBCIEIBXT666666NAmSfUzsFIGfWBRrHUybQlP9L2OHuBcD -----END PRIVATE KEY-----`; // 2. 创建私钥对象 const privateKey = crypto.createPrivateKey({ key: privateKeyPem, format: 'pem' }); // 3. 准备要签名的数据 const dataToSign = 'eyJhbGciOiJFZERTQSIsImtpZCI6IkM1Qj123MjJUREoiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiIyQTJGSk5USkY5IiwiaWF0Ijo123YzNzk5ODU3LCJleHAiOjE3NjM4MDE2NTd9';
// 4. 执行签名 const signature = crypto.sign(null, Buffer.from(dataToSign), privateKey);
// 5. 转换为 Base64URL const signatureBase64 = signature.toString('base64url');
console.log('签名结果:', signatureBase64);
ps:其实上面这个示例我也是问ai的,我对nestjs还不太熟,但可以保证的是我使用nestjs成功获取了jwt,并且能够调用天气api。
代码里的signatureBase64就是第三步要拿到的Signature了
好,三个部分都拿到了,把这三个东西用逗号连起来就是我们要获取的jwt了!!
简单来说:jwt = base64url(Header).base64url(Payload).base64url(私钥签名(base64url(Header).base64url(Payload)))
五:调用api
太棒了,就差临门一脚了
const token = "你的JWT Token"; // eyJhbGciOiJFZERTQSIs... const apiUrl = "你的API Host/v7/weather/now";
请求头:
const headers = { 'Authorization': `Bearer ${token}`, 'Accept-Encoding': 'gzip' };
注意:这儿为什么有个写死的值呢,按官方的说法是:和风天气的Web API默认采用Gzip进行压缩,这将极大的减少网络流量,加快请求。
传参:
const params = { location: '101010100', // 北京 lang: 'zh' // 中文 };
请求示例:
// 使用 axios const response = await axios.get(apiUrl, { headers, params });
结果示例:
{ "data": { "code": "200", "updateTime": "2025-11-22T17:36+08:00", "fxLink": "https://www.qweather.com/weather/beijing-101010100.html", "now": { "obsTime": "2025-11-22T17:30+08:00", "temp": "9", "feelsLike": "7", "icon": "150", "text": "晴", "wind360": "225", "windDir": "西南风", "windScale": "1", "windSpeed": "2", "humidity": "35", "precip": "0.0", "pressure": "1014", "vis": "13", "cloud": "2", "dew": "-9" }, "refer": { "sources": [ "QWeather" ], "license": [ "QWeather Developers License" ] } }, "code": 200, "message": "success", "success": true, "timestamp": "2025-11-22T09:37:19.186Z" }
到这儿,算是基本实现了api的简单调用。

浙公网安备 33010602011771号