Making Yahoo Weather API request with OAuth 1

前端 未结 4 840
刺人心
刺人心 2020-12-14 19:46

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

4条回答
  •  囚心锁ツ
    2020-12-14 20:13

    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=
    
    
    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 = '
    '+weather.item.condition.temp+'°'+weather.units.temperature+'
    Feels like: '+weather.wind.chill+'°
    '; $("#weather").html(html); }); }, });

提交回复
热议问题