Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making Yahoo Weather API request with OAuth 1

I ran into a problem with Yahoo Weather API because it wasn't giving me any data. After visiting YDN website I've found out that all requests should be updated to OAuth 1 starting from March 15th (but I got working it just today!). It's also said to include Yahoo App key and secret. What the request url should look like now, when I must use my app key and secret?

Before, I got such request string: https://query.yahooapis.com/v1/public/yql?q=SOME_QUERY&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=

UPDATE

13 minutes after I originally asked this question API calls with /v1/public/ endpoint are working again. But it's still interesting for me to get an answer to my question.

UPDATE

It's down again :(

like image 500
phbelov Avatar asked Mar 23 '16 18:03

phbelov


3 Answers

If you simply replace

http://weather.yahooapis.com/

with

http://xml.weather.yahoo.com/

it should work ;)

like image 147
Tadej Avatar answered Oct 18 '22 22:10

Tadej


Current Solution As of Mid-April 2016 - Yahoo is Allowing YQL Requests Without Oauth Again Due to Developer Outrage

You can once again write a query without any authentication like the following:

https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22nome%2C%20ak%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys

Previous answers below in case they were of help for anyone. During certain periods of Yahoo's changes they did work.


Below are Older Versions of this Answer for Historical Reasons That May Also Still Work


Updated Answer After Yahoo's Latest Round of Updates - Insecure OAuth Workaround

You will need to create a Yahoo account & then create a web application at https://developer.yahoo.com/apps/create/

You will then need to use an OAuth Library to properly encode your Client ID & Client Secret. Here is an example in JavaScript based off a Yahoo Example Page & a 2008 Blog Article by Paul Donnelly. This generates an encoded URL to use to request a weather feed.

//Fill in your consumer Key & Secret from Yahoo's App & adjust location as needed. 
//This Key & Secret combination is invalid & won't work for you
var consumerKey = "dj0yJmk9NkRjbXpjUEhPbjlnJmQ9WVdrOVFUQTFaV2wxTjJrbXnHbz3NQSktJnM9Y29uc3VtZXJzZWNyZXQmeD0wOQ--";
var consumerSecret = "9bea8a9k3934d16365ek7e23e0abo1bba4q5c03c";
var locationToQuery = "90210"; //Can be zip code or anything that works in the query select woeid from geo.places(1) where text=<Your Location>


var makeSignedRequest = function(ck,cs,loc) {

    var encodedurl = "https://query.yahooapis.com/v1/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22"+loc+"%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";

    var accessor = { consumerSecret: cs, tokenSecret: ""};          
    var message = { action: encodedurl, method: "GET", parameters: [["oauth_version","1.0"],["oauth_consumer_key",ck]]};

    OAuth.setTimestampAndNonce(message);
    OAuth.SignatureMethod.sign(message, accessor);

    var parameterMap = OAuth.getParameterMap(message);
    var baseStr = OAuth.decodeForm(OAuth.SignatureMethod.getBaseString(message));           
    var theSig = "";

    if (parameterMap.parameters) {
        for (var item in parameterMap.parameters) {
            for (var subitem in parameterMap.parameters[item]) {
                if (parameterMap.parameters[item][subitem] == "oauth_signature") {
                    theSig = parameterMap.parameters[item][1];                    
                    break;                      
                }
            }
        }
    }

    var paramList = baseStr[2][0].split("&");
    paramList.push("oauth_signature="+ encodeURIComponent(theSig));
    paramList.sort(function(a,b) {
        if (a[0] < b[0]) return -1;
        if (a[0] > b[0]) return 1;
        if (a[1] < b[1]) return  -1;
        if (a[1] > b[1]) return 1;
        return 0;
    });

    var locString = "";
    for (var x in paramList) {
        locString += paramList[x] + "&";                
    }

    var finalStr = baseStr[1][0] + "?" + locString.slice(0,locString.length - 1);

    return finalStr;
};

//Use the encodedURL to make your request
var encodedURL = makeSignedRequest(consumerKey, consumerSecret, locationToQuery); 

It should be noted never to show your consumer key or consumer secret to the public. You can use your own Yahoo Credentials in this Plunkr: http://plnkr.co/edit/EvLbgs

Original Answer

Unfortunately as of right now, the servers are down to create that app. Ideally, once they're back up you can use server side code to do the oauth part. I'll try to edit this answer when that happens. According to Yahoo the URL will be the same except without the /public part. The big difference will be that you need to send request headers with the URL that authenticate your account.

Here's a temporary fix until then. You can still use a YQL query geo.places with a zip code to get the woeid.

select * from geo.places where text=90210 limit 1

You can then grab your woeid from there & use it in the following url to get an xml feed:

http://weather.yahooapis.com/forecastrss?w=WOEID_GOES_HERE

I've created a Plunker as an example of this temporary fix here: http://plnkr.co/edit/dClPDtnToMhHqvKpfCzj?p=preview

Here's the gist of it though using jQuery:

var zipCode = 90210;

$.ajax({
    dataType: "json",
    headers:  { "Accept": "application/json; odata=verbose" },
    url: "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.places%20where%20text%3D"+zipCode+"%20limit%201&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys",
    beforeSend: function(xhr){xhr.setRequestHeader('Accept', 'application/json; odata=verbose');},
    success: function(data){
        $.getJSON("https://query.yahooapis.com/v1/public/yql?callback=?", {
            q: "select * from xml where url=\"https://weather.yahooapis.com/forecastrss?w="+data.query.results.place.locality1.woeid+"\"",
            format: "json"
        },function (data) {
          var weather = data.query.results.rss.channel;
          var html = '<div><span class="temperature">'+weather.item.condition.temp+'<span class="degree">&deg;</span><sup>'+weather.units.temperature+'</sup></span><br><span class="wind-chill">Feels like: '+weather.wind.chill+'<span class="degree">&deg;</span></span></div></a>';
          $("#weather").html(html);
        });
    },
});
like image 29
mattferderer Avatar answered Oct 18 '22 22:10

mattferderer


We finally got our yql weather working again using two-legged authorization using yosdk: (https://github.com/isaacs/authentipede)

And using this script

<?php
include_once("yosdk/lib/Yahoo.inc");

define("API_KEY","your-api-key-here");
define("SHARED_SECRET","your-secret-here");
YahooLogger::setDebug(true);

$twoleg = new YahooApplication (API_KEY, SHARED_SECRET);
$query = 'select * from weather.forecast where woeid in (select woeid from geo.places(1) where text="84054") and u="f"';
print_r ($results);

I found this from this discussion: (How do I get started with oauth for YQL for historical stock data?)

like image 29
Gian O'Neil Avatar answered Oct 18 '22 20:10

Gian O'Neil