天气预报接口:SmartWeather API中key的计算方法
这个代码大家都蛮感兴趣,我在git开源了一个用于收集天气信息的系统,基于python语言的,请大家参考:
https://github.com/BerlinSun/WeatherForecast
----------------------
最近申请到SmartWeatherAPI天气预报接口的使用权限,开始着手我的实时天气预报系统的开发,主要开发的版本使用的是Python脚本,成果将于近期以系列文章与大家见面。今天在这里我和大家探讨一下SmartWeatherAPI中key的计算方法,并提供C++程序源码供大家参考。
开发环境: Ubuntu + GCC4.7
零、 SmartWeather API的申请
SmartWeatherAPI(简称“SWA接口”)是中国气象局面向网络媒体、手机厂商、第三方气象服务机构等用户,通过web方式提供数据气象服务的官方载体。是国内首个面向个人网站、开发爱好者和服务机构的气象服务API数据开发接口(申请地址戳着里)。申请过程需要填写一个表格,发送到官方邮箱,人工审核通过后会回复邮件,随信提供appid和private_key等信息。
回复邮件部分内容如下(appid和private_key为私密信息,故用红色横线代替):
您好: 恭喜您的申请已通过审核,以下是为您分配的鉴权信息: appid:-------------- private_key:------------------------ 接口使用说明请参考《SmartWeatherAPI_Lite_WebAPI 版产品使用说明书》,区域列表:请见附件areaid_list.xlsx。 该鉴权信息仅限您个人或本公司使用,如有泄露我们将撤销您的使用权限,必要时将追究相关责任。 最后,非常感谢您的参与。
一、 WebAPI接口说明书
接口说明说在上面所提到的API接口申请的网站可以下载到,下面就起说明书中几个要点做以下说明:
1. 接口说明
请求方式: http get
接口组成: 由固定 URL 加 5 个不同的参数组成,完整URL需客户端经过固定方式加密后使用。
数据返回: json
完整URL: http://webapi.weather.com.cn/data/?areaid=""&type=""&date=""&appid=""&key=".urlencode($key)
输入参数:
areaid: 区域id,审核通过后邮件中有个附件,提供的就是现有的所有区域的id号。
type: 数据类型(实况: observe, 指数: index, 常规预报: forecast3d)。
date: 客户端日期,按照格式yyyyMMddHHmm获取客户端当前时间。
appid: 固定分配的型号标识,审核通过后邮件告知(传递参数时:截取 appid 的前 6 位; 生成公钥时:取完整的 appid)。
key: 令牌,有公钥(public_key)和私钥(private_key)通过固定算法加密生成。
2. 加密方式
加密算法是今天博客的基础,大家仔细阅读。加密算法中涉及到的三个要素分别为:
- private_key: 审核通过后,邮件中会提供。private_key仅负责与 public_key 共同合成 key 传参,私钥不可见,客户端与服务端各存储一份;
- public_key: 不包含key在内的完整URL的其他部分(此处appid为完整appid);
- key的算法: 说明书中提供的是php中的算法代码,如下
key = base64_encode(hash_hmac('sha1', $public_key, $private_key, TRUE));
key加密后,通过 urlencode 对其编码后传参。
举例说明,除去key部分的URL如下:
http://webapi.weather.com.cn/data/?areaid=101010100&type=index&date=201211281030&appid=cf2d61521456sads
私钥private_key假设为: private_key
我们使用上述算法首先计算出加密后的key,得到key之后使用urlencode方法处理我们加密得到的key,结果为:
A%2Fp2QJ4R%2FD3FFCr6XwUCyNP56Y0%3D
则我们最后的输入URL为:
http://webapi.weather.com.cn/data/?areaid=101010100&type=index&date=201211281030&appid=cf2d61&key=A%2Fp2QJ4R%2FD3FFCr6XwUCyNP56Y0%3D
3. 返回数据
输出实例:
{ "l" : { "l1" : "14", "l2" : "46", "l3" : "2", "l4" : "6", "l7" : "12:00" } }
其中:
l1: 表示当前温度(摄氏度);
l2: 表示当前湿度(%);
l3: 表示当前风力(级);
l4: 表示当前风向编号(主页有文献可以查到具体的风向);
l7: 表示实况发布时间。
当前不同的type请求结果是大相径庭的,具体的其他2类的我在这里不一一说明,需要了解的童鞋可以参考官方的文档,这里顺便列举一个type=forecast3d的返回结果:
{ "c" : { "c1" : "101270101", "c10" : "1", "c11" : "028", "c12" : "610000", "c13" : "104.071", "c14" : "30.67", "c15" : "507", "c16" : "AZ9280", "c17" : "+8", "c2" : "chengdu", "c3" : "成都", "c4" : "chengdu", "c5" : "成都", "c6" : "sichuan", "c7" : "四川", "c8" : "china", "c9" : "中国" }, "f" : { "f0" : "201401241100", "f1" : [
{ "fa" : "01", "fb" : "01", "fc" : "16", "fd" : "2", "fe" : "4", "ff" : "4", "fg" : "0", "fh" : "0", "fi" : "07:59|18:32" },
{ "fa" : "01", "fb" : "01", "fc" : "16", "fd" : "2", "fe" : "4", "ff" : "4", "fg" : "0", "fh" : "0", "fi" : "07:58|18:33" },
{ "fa" : "01", "fb" : "02", "fc" : "14", "fd" : "4", "fe" : "4", "ff" : "4", "fg" : "0", "fh" : "0", "fi" : "07:58|18:34" } ] } }
二、 加密过程分析
在动手实现加密方法之前,我在想,首先我应该知道正确的加密结果撒,让我看到正确的返回数据之后再去做这件事情不是更有意义。看官方提供的是php的方法,那我就先用php试一下呗,可我没有安装php阿,总不能因为做个小测试还整个php环境吧,麻烦!幸好有php online帮到我http://writecodeonline.com/php/:
上面实例中的结果就是这么来的:
echo urlencode(base64_encode(hash_hmac('sha1', "http://webapi.weather.com.cn/data/?areaid=101010100&type=index&date=201211281030&appid=cf2d61521456sads", "private_key", TRUE)));
当然,实例中的URL是不会返回正确数据的,因为我们用的appid和private_key都是假造的,我在测试的过程使用的是我申请到的相关信息。
结果返回成功了,我们开始分析如何使用C++去实现这个加密过程吧!
1. 肢解加密过程
一口吃不成一个胖子,我们一步一步来,从最内层开始,从hash_hmac入手,说白了不就是hash过程了,这时候我想到了openssl,是的,就是他了!首先我们在php环境中求出我们这一步的结果再说:
echo hash_hmac('sha1', "http://webapi.weather.com.cn/data/?areaid=101010100&type=index&date=201211281030&appid=cf2d61521456sads", "private_key", TRUE);
结果如下:
�v@��=�*�_�����
使用openssl之前,让我们分析以下php中的hash_hmac函数中的几个参数,前三个估计一目了然,最后一个是什么意思呢?函数原型如下:
string hash_hmac( string $algo , string $data , string $key [, bool $raw_output = false ] )
最后一个参数raw_output解释为: When set to TRUE
, outputs raw binary data. FALSE
outputs lowercase hexits.
好了,我们开始用openssl试试,先不着急用C++,先在bash下用command试试:
echo -n "http://webapi.weather.com.cn/data/?areaid=101010100&type=index&date=201211281030&appid=cf2d61521456sads" | openssl dgst -sha1 -binary -hmac "private_key"
看到这里的-binary参数没有,这就是我之前为什么为专门分析hash_hmac最后一个参数的原因,因为我当时就在这里少了-binary参数,导致出来的结果老是对不上。好了,结果表明,和php的结果一致。
继续肢解,开始第二步,base64_encode函数的分析,同样, 先在php中来过:
echo base64_encode(hash_hmac('sha1', "http://webapi.weather.com.cn/data/?areaid=101010100&type=index&date=201211281030&appid=cf2d61521456sads", "private_key", TRUE));
结果如下:
A/p2QJ4R/D3FFCr6XwUCyNP56Y0=
我们来看看base64_encode函数的原型:
string base64_encode ( string $data )
这个函数,见名知意,就是对数据进行base64编码。在linux下有现成的工具,即base64:
echo -n "http://webapi.weather.com.cn/data/?areaid=101010100&type=index&date=201211281030&appid=cf2d61521456sads" | openssl dgst -sha1 -binary -hmac "private_key" | base64
测试通过,我们开始最后一步,urlencode函数做什么,这个问题在之前一篇文章:http://www.cnblogs.com/berlin-sun/p/translateonline.html 中提到过,其实就是对url重新进行编码,Returns a string in which all non-alphanumeric characters except -_. have been replaced with a percent (%) sign followed by two hex digits and spaces encoded as plus (+) signs.
2. 具体实现
hmac过程:
#include <openssl/hmac.h> unsigned char *digest;
digest = HMAC(EVP_sha1(), key, strlen(key), (unsigned char*)weather_api, strlen(weather_api), NULL, NULL);
base64过程:
#include <openssl/bio.h>
#include <openssl/buffer.h> char *base64(const unsigned char* input, int length)
{
BIO *bmem, *b64;
BUF_MEM *bptr; b64 = BIO_new(BIO_f_base64());
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, input, length);
BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr); char *buff = (char *)malloc(bptr->length);
memcpy(buff, bptr->data, bptr->length-); buff[bptr->length-] = ;
BIO_free_all(b64); return buff;
} char *base64Digest = base64(digest, strlen((char *)digest));
urlencode过程:
#inlcude “curl/curl.h” CURL * curl;
curl = curl_easy_init(); char *encode_key = curl_easy_escape(curl, base64Digest, );
目前,C++程序就完成了这些,结果已经成功返回,如下图:
这就是我昨天晚上6点到7点半做的所有事情,然后得到女朋友的极大吐槽:一天到黑都在整,烦
编程改变世界,我是一个快乐的程序猿,谢谢大家阅读!
天气预报接口:SmartWeather API中key的计算方法的更多相关文章
- 开源免费的天气预报接口API以及全国所有地区代码(国家气象局提供)
天气预报一直是各大网站的一个基本功能,最近小编也想在网站上弄一个,得瑟一下,在网络搜索了很久,终于找到了开源免费的天气预报接口API以及全国所有地区代码(国家气象局提供),具体如下: 国家气象局提供的 ...
- day71:drf:API接口&Restful API规范&Django Rest Framework&drf中的序列化和反序列化功能
目录 1.web应用模式 2.API接口 3.Restful API规范 4.序列化 5.Django Rest Framework 1.drf的简单介绍 2.drf的特点 3.如何安装drf 4.d ...
- 开源免费天气预报接口API以及全国所有地区代码!!(国家气象局提供) 【转】
国家气象局提供的天气预报接口 接口地址: http://www.weather.com.cn/data/sk/101010100.html http://www.weather.com.cn/data ...
- 开源免费天气预报接口API以及全国全部地区代码!!(国家气象局提供)
国家气象局提供的天气预报接口 接口地址: http://www.weather.com.cn/data/sk/101010100.html http://www.weather.com.cn/data ...
- JavaWeb学习之JDBC API中常用的接口和类
JDBC API中包含四个常用的接口和一个类分别是: 1.Connection接口 2.Statement接口 3.PreparedStatement接口 4.ResultSet接口 5.Driver ...
- 开源免费天气预报接口API以及全国所有地区代码[值得收藏]
国家气象局提供的天气预报接口 接口地址: http://www.weather.com.cn/data/sk/101010100.html http://www.weather.com.cn/data ...
- (转)免费天气预报接口API以及全国所有地区代码!!
国家气象局提供的天气预报接口 接口地址: http://www.weather.com.cn/data/sk/101010100.html http://www.weather.com.cn/data ...
- Java基础学习总结(67)——Java接口API中使用数组的缺陷
如果你发现在一个接口使用有如下定义方法: public String[] getParameters(); 那么你应该认真反思.数组不仅仅老式,而且我们有合理的理由避免暴露它们.在这篇文章中,我将试图 ...
- .NET Core WEB API中接口参数的模型绑定的理解
在.NET Core WEB API中参数的模型绑定方式有以下表格中的几种: 微软官方文档说明地址:https://docs.microsoft.com/zh-cn/aspnet/core/web-a ...
随机推荐
- 微软分布式机器学习工具包DMTK——初窥门径
在现在机器学习如日中天的大背景下,微软亚洲研究院的实习岗位中,机器学习组的工作也是维护DMTK,参与算法改进,那么在此之前我们得了解DMTK是个啥. DMTK由一个服务于分布式机器学习的框架和一组分布 ...
- 面试题-谈谈你对Java平台的理解
平台无关性 GC 语言特性 面向对象 类库 异常处理 一次编译到处运行 JVM如何加载Class文件 Java反射 ClassLoader 种类 双亲委派机制 loadcalss和forName
- python基础一 day15 内置函数
'\r' 回车,回到当前行的行首,而不会换到下一行,如果接着输出的话,本行以前的内容会被逐一覆盖: '\n' 换行,换到当前位置的下一行,而不会回到行首: # print()# input()# le ...
- c#和Java中的抽象类
应用场景:当父类中的方法不知道如何去实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法. 比如:描述一个图形.圆形. 矩形三个类.不管哪种图形都会具备计算面积与周长的行为,但是每种图形计算的方式 ...
- ReactiveCocoa概念解释进阶篇
1.ReactiveCocoa常见操作方法介绍 1.1 ReactiveCocoa操作须知 所有的信号(RACSignal)都可以进行操作处理,因为所有操作方法都定义在RACStream.h中,因此只 ...
- 性能优化之MySQL优化(慕课)
MySQL数据库优化 1-1MySQL优化简介 数据库优化的目的 避免出现页面访问错误 由于数据库连接timeout产生5XX错误 由于慢查询造成页面无法加载 由于阻塞造成数据无法提交 增加数据库的稳 ...
- bash编程之case语句,函数
bash脚本编程:之case语句 条件测试: 0: 成功 1-255: 失败 命令: [ expression ] [[ expression ]] test expression exP ...
- Python的ORM介绍
实现方法: SQLOject peewee Django's ORM SQLAlchemy
- 跟踪路由 tracert
由于最近遇到网络出现故障的问题,便使用到Tracert来确定了下出现故障的网络节点 记录下tracert命令相关内容 1. 简介 2. Tracert工作原理... 3. 常用参数 4. 使用示例与输 ...
- 【HIHOCODER 1599】逃离迷宫4
描述 小Hi被坏女巫抓进一座由无限多个格子组成的矩阵迷宫. 小Hi一开始处于迷宫(x, y)的位置,迷宫的出口在(a, b).小Hi发现迷宫被女巫施加了魔法,假设当前他处在(x, y)的位置,那么他只 ...