在 Google Apps Script Web 应用程序中使用 Facebook API? [英] Use the Facebook API in a Google Apps Script web app?

查看:20
本文介绍了在 Google Apps Script Web 应用程序中使用 Facebook API?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Google Apps 脚本作为 Web 应用程序作为后端来创建 Facebook 应用程序.唯一似乎适用的 Facebook API 是

下载 Facebook 图形.阅读该做什么和不该做什么

创建 Facebook 登录按钮

<a href="https://www.facebook.com/dialog/oauth?client_id=YourClientID&redirect_uri=https://script.google.com/macros/s/YourAppsScript/exec?&response_type=token&scope=publish_stream"><img src="https://FacebookGraphic.png" height="95%" width="95%"></a>

设计 Facebook 登录按钮的样式

#FbLog {填充:10px;背景颜色:白色;左边距:自动;边距右:自动;光标:指针;}

窗口加载代码

这是我用来捕获 Facebook 令牌的 window.onload 客户端代码.这仅用于捕获 Facebook 令牌,而不用于验证令牌.我的应用程序允许 Facebook 登录和常规登录.Facebook 令牌的验证在另一个代码中完成.

window.onload=function(){//console.log("这个onload确实运行了");//从浏览器地址栏中获取URL//根据情况,URL 可以附加多个不同的字符串.//1) 使用 Facebook 登录.2) 有人想买一个物品 3) 有人想输入一个待售物品.//除了FB登录以外的任何情况都是在后台发起的.window.daURL = window.location;window.urlStrng = daURL.toString();//console.log("url:" + urlStrng);//如果有FaceBook登录,url字符串中会有hashtagwindow.hashPos = urlStrng.indexOf("#");如果(window.hashPos > 0){mainStart('InputBlock', 'InputForm');window.urlEnd = urlStrng.split("#", 2);window.urlTkn = urlEnd[1].split("&", 2);window.fbAcsTkn = urlTkn[0].split("=", 2);window.finalTkn = fbAcsTkn[1];window.scndExpire = urlStrng.substring(urlStrng.indexOf("_in=")+4, urlStrng.length);console.log("scndExpire:" + scndExpire);google.script.run.withFailureHandler(onFailure).withSuccessHandler(showFBsuccess).processFB_LogIn(window.finalTkn, scndExpire)}别的 {//如果不是Facebook登录,进入下两个选项//如果 URL 字符串中包含 &L,则由于有人点击了购买",因此正在传递商品列表信息window.whatToLoad = urlStrng.indexOf("&L");console.log("加载运行的第二个选项");如果(window.whatToLoad > 0){google.script.run.withFailureHandler(onFailure).withSuccessHandler(injectBuyForm).include('MutualCmit');} 别的 {google.script.run.withFailureHandler(onFailure).withSuccessHandler(injectSignInForm).include('登录');};};};

请注意,即使 Facebook 登录是在前端触发的,验证也会在 .gs 代码中进行.有人可以注入虚假的 Facebook 令牌,但它不会通过服务器端代码中的检查.

这是处理 Facebook 登录的 .gs 代码:

验证 Facebook 令牌 GS 代码

//我把这个缓存行放在`.gs`文件的最顶部.另一个代码//可以放在更低的地方.var cache = CacheService.getPrivateCache();函数 processFB_LogIn(argFB_Tkn, expTime) {cache.put('fbTkn', argFB_Tkn, 4000);cache.put('fbExpr', expTime, 4000);var meFBtkn = cache.get('fbTkn');Logger.log("FaceBook 代币:" + meFBtkn);//此部分用于验证(调试)用户实际通过Facebook登录//第一个 FB 令牌是在用户登录后和此应用程序脚本加载时从 URL 传入的.//重要的!!!重要的!!!你必须逃避|带有代码 %7C 的字符var AppAccssTkn = 'YourAppID%7YourAppToken';//除非应用程序秘密更改,否则这永远不会改变var optnGetTkn = {"method": "get", "muteHttpExceptions" : true};//此调试"用户登录 Facebook 后 URL 中返回的令牌.您应该"验证令牌是真实的.var rsltDebug = UrlFetchApp.fetch("https://graph.facebook.com/debug_token?input_token=" + meFBtkn + "&access_token=" + AppAccssTkn, optnGetTkn);var debugTxt = rsltDebug.getContentText();Logger.log("debugTxt:" + debugTxt);var jsonObj = JSON.parse(debugTxt);Logger.log("jsonObj:" + jsonObj);//这是FB用户IDvar useIdTxt = jsonObj.data.user_id;cache.put('pubIDcache', useIdTxt, 4000);var tknValid = jsonObj.data.is_valid;Logger.log("调试结果:" + useIdTxt);Logger.log("tknValid:" + tknValid);var getFbUseName = UrlFetchApp.fetch("https://graph.facebook.com/" + useIdTxt + "/?fields=first_name&access_token=" + AppAccssTkn, optnGetTkn);var objUseName = JSON.parse(getFbUseName);var arryFirstName = objUseName.first_name;Logger.log("用户名:" + arryFirstName);cache.put('fbFrstName', arryFirstName, 4000);如果(tknValid === false){返回无效";}否则如果(arryFirstName != null){//这是判断某人是否登录的方式.cache.put('imin', '9847594ujglfugfjogj', 4000);返回 arryFirstName;};};

您需要一个一次性 App 令牌,除非您的 App Secret 发生变化,否则该令牌不会发生变化.您必须使用一次性运行的一段代码来生成它.

使用此代码获取您的应用访问令牌:

//Facebook App Token 永远不会改变,除非你去 Facebook 开发者控制台,并且你//更改应用程序密钥.所以,不要一直请求新的应用程序令牌.只拿一次,然后//将其硬编码到后端秘密函数中.//应用程序令牌可用于修改您的应用程序,但您可以手动"执行此操作函数 getOneTimeFB_AppToken() {Logger.log("getOneTimeFB_AppToken 运行");//将此信息保密//生成应用访问令牌var ysshAppID = '你的应用程序 ID';var ysshAppSecret = '你的应用程序秘密';var optnAppTkn = {方法":获取"};var getAppTknURL = "https://graph.facebook.com/oauth/access_token?client_id=" + ysshAppID + "&client_secret=" + ysshAppSecret + "&grant_type=client_credentials"var getAppTkn = UrlFetchApp.fetch(getAppTknURL, optnAppTkn);Logger.log("GET 返回的对象:" + getAppTkn)var myAppTkn = getAppTkn.getContentText();Logger.log("myAppTkn:" + myAppTkn);};

发布到 Facebook GS 代码

function fncPostItemFB(arg1ToPost, arg2ToPost, arg3ToPost, argEtcToPost) {var fbCacheTkn = cache.get('fbTkn');Logger.log("fbCacheTkn:" + fbCacheTkn);如果(fbCacheTkn === null){返回假;};Logger.log("fncPostItemFB 运行:" + fbCacheTkn);返回 fncPostSecurly_(arg1ToPost, arg2ToPost, arg3ToPost, argEtcToPost);};函数 fncPostSecurly_(arg1ToPost, arg2ToPost, arg3ToPost, argEtcToPost) {Logger.log("fncPostSecurly 运行");var sttsUpdate = argToPost +您要在此处发布的文本"+ argToPost;var fromLogInTkn = cache.get('fbTkn');Logger.log("缓存FB token:" + fromLogInTkn);//这是增加的安全性 https://developers.facebook.com/docs/graph-api/securing-requests/var appsecret_sig = Utilities.computeHmacSha256Signature(fromLogInTkn, "YourAppSecret");var optnPostFB = {"method": "post"};//var PostToFB_URL = "https://graph.facebook.com/FacebookPageOrGroupID/feed?message=" + sttsUpdate + "&access_token="+ fromLogInTkn;//+ "&appsecret_proof=" + appsecret_sig;//发布到页面var whatHappened = UrlFetchApp.fetch(PostToFB_URL, optnPostFB );//从facebook返回的是一个对象.必须转换为字符串.var strFrmFbObj = whatHappened.getContentText();Logger.log("Post 返回值:" + strFrmFbObj);//当一个帖子成功发布到Facebook时,一个带有id值的返回对象被传回.var rtrnVerify = strFrmFbObj.indexOf('{"id":"');Logger.log("rtrnVerify:" + rtrnVerify);如果(rtrnVerify!= -1){返回真;} 别的 {返回假;};};

发布到 Facebook 前端 Javascript 代码

I'm trying to create a Facebook app using a Google Apps Script as web app, as the back-end. The only Facebook API that seems applicable is the Javascript SDK, but I can't even get that one to work.
The current problem I'm having is that the Facebook JS SDK uses Javascript identifiers that end with: "__". Google Apps Script restricts names that end in double underscores.

If I use a modified copy of Facebook's JS file without double underscores in names, I get this error:
Refused to display [URL] in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'

Any idea how to get GAS playing nicely with FB?

解决方案

I've figured out how to use Apps Script UrlFetchApp.fetch and the HTML Service to log a user in to my Apps Script App with Facebook. I can also post to Facebook with Apps Script.

  • You don't need the Facebook Javascript SDK

General Overview

There are 8 different Facebook Platforms:

The Facebook Platform that I'm using with Apps Script is the Website platform. The Website does not run embedded in Facebook.

What you can't do: (As far as I know)

  • There is a difference between a Website that interacts with Facebook, and a Facebook Page Tab. A Facebook Page Tab runs embedded in Facebook. My experience is, that the Apps Script URL causes problems with a Facebook Page Tab. The URL for Apps Script has lots of stuff appended to the end that Facebook seems to strip out. (Or something like that) I've tried many different variations of Google products with Facebook. You can use a Google Site as a Facebook Page Tab, but if you embed a Google Apps Script inside a Site, that is then inside a Facebook Page Tab, it causes a Cross Domain error. So, the only option I can get to work is the Website option.

A sort of work around that I use for the Page Tab problem, is to use Thunderpenny Static HTML as a Facebook Page Tab, that then links to either my Apps Script App, or a GAE App. (Depending upon whether I need HTTP S or not)

You could use a Google Site as the Page Tab, but Thunderpenny can design an app with HTML, Javascript and CSS as you normally would. OH! And I've tried using the Facebook Javascript SDK inside of Thunderpenny, and got nowhere with that. Besides, the Thunderpenny app doesn't have a backend, Apps Script does have a backend (.gs code) where you can hide your Facebook App Token.

The basics steps are:

  • Trigger a link to Facebook oauth from your App.
  • href="https://www.facebook.com/dialog/oauth?client_id=yourIDhereNoQuotes&redirect_uri=https://script.google.com/macros/s
  • Capture the returned Facebook token from the URL with an OnLoad function
  • You can NOT process the Facebook redirect URL back to your application with doGet(e). Here's why. Apps Script needs to see a question mark in the URL in order to parse the URL. Facebook returns a URL with a different configuration.
  • Run a script when your app loads to process the Facebook Token
  • window.onload=function(){};
  • The onload function runs a .gs function to verify the token
  • Use UrlFetchApp.fetch to debug the token
  • Cache the login status in private cache
  • var cache = CacheService.getPrivateCache();
  • Check log in status when needed.

Note that Facebook keeps track of your app login status independently. But your app could have a logged in status of still active when the Facebook token has expired. So you need a way to check that.

Use Official Facebook Graphics

Brand Resources - Facebook

Download Facebook graphics. Read Do's and Dont's

Create a Facebook Login Button

<div id="FbLog">
    <a href="https://www.facebook.com/dialog/oauth?client_id=YourClientID&redirect_uri=https://script.google.com/macros/s/YourAppsScript/exec?&response_type=token&scope=publish_stream"><img src="https://FacebookGraphic.png" height="95%" width="95%"></a>
</div>

Style the Facebook Login Button

#FbLog {
    padding: 10px;
    background-color: white;
    margin-left:auto;
    margin-right:auto;
    cursor: pointer;
}

Window OnLoad Code

Here is the window.onload client side code that I use to capture the Facebook token. This is only used to capture the Facebook token, not to validate the token. My app allows both Facebook login, and a regular login. Validation of the Facebook token is done in another code.

window.onload=function(){
  //console.log("This onload did run");

  //get the URL out of the browsers address bar
  //the URL can have multiple different strings attached depending upon the situation.
  //1)Sign in with Facebook. 2) Someone wanting to buy an item 3) Someone wanting to input an item for sale.
  //Any situation other than the FB log in is initiated in the back end.
  window.daURL = window.location;
  window.urlStrng = daURL.toString();

  //console.log("url: " + urlStrng);
  //If there was a FaceBook login, there will be a hashtag in the url string
  window.hashPos = urlStrng.indexOf("#");
  if (window.hashPos > 0) {
    mainStart('InputBlock', 'InputForm');
    window.urlEnd = urlStrng.split("#", 2);
    window.urlTkn = urlEnd[1].split("&", 2);
    window.fbAcsTkn = urlTkn[0].split("=", 2);
    window.finalTkn = fbAcsTkn[1];

    window.scndExpire = urlStrng.substring(urlStrng.indexOf("_in=")+4, urlStrng.length);
    console.log("scndExpire: " + scndExpire);

    google.script.run.withFailureHandler(onFailure)
    .withSuccessHandler(showFBsuccess)
    .processFB_LogIn(window.finalTkn, scndExpire)
  }
  else {
    //If it's not a Facebook log in, go to next two choices
    //If the URL string has &L in it, then item listing info is being passed because someone clicked 'Buy'
    window.whatToLoad = urlStrng.indexOf("&L");
    console.log("Second option of onload ran");
    if (window.whatToLoad > 0) {
      google.script.run.withFailureHandler(onFailure)
        .withSuccessHandler(injectBuyForm)
        .include('MutualCmit');
     } else {
     google.script.run.withFailureHandler(onFailure)
       .withSuccessHandler(injectSignInForm)
       .include('SignIn');
     };
  };
};

Note that even though the Facebook login is triggered in the front end, the validation happens in .gs code. Someone could inject a false Facebook token, but it's not going to pass inspection in the server side code.

This is the .gs code to process the Facebook Login:

Validation of Facebook Token GS Code

//I put this cache line at the very top of the `.gs` file. The other code
// can be put somewhere lower.

var cache = CacheService.getPrivateCache();

function processFB_LogIn(argFB_Tkn, expTime) {
    cache.put('fbTkn', argFB_Tkn, 4000);
    cache.put('fbExpr', expTime, 4000);

    var meFBtkn = cache.get('fbTkn');

    Logger.log("FaceBook Token: " + meFBtkn);

     //This section is for verifying (debug) the user actually signed in through Facebook
    //The first FB token is passed in from the URL right after the user signs in, and when this apps Script loads.
    //IMPORTANT!!!    IMPORTANT!!!   You MUST escape the | character with code %7C

    var AppAccssTkn = 'YourAppID%7YourAppToken'; //This never changes unless app secret changes
    var optnGetTkn = {"method" : "get", "muteHttpExceptions" : true};
      //This 'Debugs' the token returned in the URL after the user signed in with Facebook.  You "should" verify that the token is real.
      var rsltDebug = UrlFetchApp.fetch("https://graph.facebook.com/debug_token?input_token="  + meFBtkn  + "&access_token=" + AppAccssTkn, optnGetTkn);
      var debugTxt = rsltDebug.getContentText();
      Logger.log("debugTxt: " + debugTxt);

      var jsonObj = JSON.parse(debugTxt);
      Logger.log("jsonObj: " + jsonObj);
      //This is the FB user ID
      var useIdTxt = jsonObj.data.user_id;
      cache.put('pubIDcache', useIdTxt, 4000);

      var tknValid = jsonObj.data.is_valid;

      Logger.log("reslt of the debug: " + useIdTxt);
      Logger.log("tknValid: " + tknValid);

      var getFbUseName = UrlFetchApp.fetch("https://graph.facebook.com/" + useIdTxt + "/?fields=first_name&access_token=" + AppAccssTkn, optnGetTkn);

      var objUseName = JSON.parse(getFbUseName);
      var arryFirstName = objUseName.first_name;
      Logger.log("user name: " + arryFirstName);

      cache.put('fbFrstName', arryFirstName, 4000);

   if (tknValid === false) {
     return 'notValid';
   }
   else if (arryFirstName != null) {
     //This is how it's determined if someone is logged in or not.
     cache.put('imin', '9847594ujglfugfjogj', 4000);
     return arryFirstName;
  };
};

You need a one time App token that won't change unless you App Secret changes. You must generate that with a one time run piece of code.

Get Your App Access Token with this code:

//A Facebook App Token never changes unless you go to the Facebook Developers Console, and you
//change the App Secret.  So, do NOT keep requesting a new App Token.  Just get it once, then
//hard code it into a backend secret function.
// The App Token can be used to modify your App, but you can just do that 'Manually'
function getOneTimeFB_AppToken() {
  Logger.log("getOneTimeFB_AppToken ran");
  //keep this info secret
  //Generate an App Access Token
  var ysshAppID = 'Your App ID';
  var ysshAppSecret = 'Your App Secret';
  var optnAppTkn = {"method" : "get"};
  var getAppTknURL = "https://graph.facebook.com/oauth/access_token?client_id=" + ysshAppID + "&client_secret=" + ysshAppSecret + "&grant_type=client_credentials"
  var getAppTkn = UrlFetchApp.fetch(getAppTknURL, optnAppTkn);
  Logger.log("Object returned from GET: " + getAppTkn)
  var myAppTkn = getAppTkn.getContentText();
  Logger.log("myAppTkn: " + myAppTkn);
};

Post to Facebook GS Code

function fncPostItemFB(arg1ToPost, arg2ToPost, arg3ToPost, argEtcToPost) {
  var fbCacheTkn = cache.get('fbTkn');
  Logger.log("fbCacheTkn: " + fbCacheTkn);

  if (fbCacheTkn === null) {
    return false;
  };
  Logger.log("fncPostItemFB ran: " + fbCacheTkn);
  return fncPostSecurly_(arg1ToPost, arg2ToPost, arg3ToPost, argEtcToPost);
};

function fncPostSecurly_(arg1ToPost, arg2ToPost, arg3ToPost, argEtcToPost) {
  Logger.log("fncPostSecurly ran");

  var sttsUpdate = argToPost + "your text to post here" + argToPost;
  var fromLogInTkn = cache.get('fbTkn');

  Logger.log("cache FB token: " + fromLogInTkn);

  //This is added security https://developers.facebook.com/docs/graph-api/securing-requests/
  var appsecret_sig = Utilities.computeHmacSha256Signature(fromLogInTkn, "YourAppSecret");
  var optnPostFB = {"method" : "post"};  //
  var PostToFB_URL = "https://graph.facebook.com/FacebookPageOrGroupID/feed?message=" + sttsUpdate + "&access_token=" 
    + fromLogInTkn; // + "&appsecret_proof=" + appsecret_sig;


    //Make a post to the Page
    var whatHappened = UrlFetchApp.fetch(PostToFB_URL, optnPostFB );
    //The return from facebook is an object.  Has to be converted to a string.
    var strFrmFbObj = whatHappened.getContentText();
    Logger.log("Return value of Post: " + strFrmFbObj);

    //When a post is successfully made to Facebook, a return object is passed back with an id value.

    var rtrnVerify = strFrmFbObj.indexOf('{"id":"');
    Logger.log("rtrnVerify: " + rtrnVerify);

    if (rtrnVerify != -1) {
      return true;
    } else {
      return false;
    };
 };

Post to Facebook Front End Javascript Code

<script>
window.WriteInput = function(whereToPost) {

    window.strngCtgry = document.getElementById('id_Category').value;
    window.strngMaker = document.getElementById('id_Maker').value;
    window.strngAskingPrice = document.getElementById('id_AskingPrice').value;
    window.strngType = document.getElementById('id_ShrtDesc').value;
    window.strngFunction = document.getElementById('id_Function').value;
    window.strngCosmetic = document.getElementById('id_Cosmetic').value;  
    window.strngDescription = document.getElementById('id_Description').value;
    window.strngUserID = document.getElementById('pubID_Holder').textContent;
    window.addrIP = document.getElementById('IP_Holder').textContent;

  if (whereToPost === 'fb') {
    console.log("fncPostToFB ran" + strngDescription);
    if (strngDescription === "" || strngAskingPrice === "") {alert("Missing Input"); return false;};
    google.script.run.withFailureHandler(postFbFail)
    .withSuccessHandler(savedToFB)
    .fncPostItemFB(strngCtgry, strngMaker, strngAskingPrice, strngType, strngDescription, strngFunction, strngCosmetic, addrIP);
  } else {
    google.script.run.withFailureHandler(onFailure)
      .withSuccessHandler(savedLst)
      .fncSaveItem(strngCtgry, strngMaker, strngAskingPrice, strngType, strngDescription, strngFunction, strngCosmetic, addrIP);
      };
    };

window.savedLst = function(rtrnInput) {
   if (rtrnInput === false) {
     alert("Failed to Save Data");
   }
   else if (rtrnInput === "NotLogged") {
     alert("You are not logged in!");
     mainStart('SignInBody', 'SignIn');
   }
   else if (rtrnInput === "noItemForPic") {
     alert("You Need to Save an Item to attach the Picture to");
   }
   else {
  alert("Your Data Was Saved!");
  //Show the listing that was just saved next to the upload Pics button
  document.getElementById('listToPic').innerHTML = document.getElementById('id_ShrtDesc').value +
    ", " + document.getElementById('id_Description').value +
    ", - Made By: " + document.getElementById('id_Maker').value +
    ", Price: $" + document.getElementById('id_AskingPrice').value;

    };
};

window.postFbFail = function() {
  alert("Failed to Post to Facebook!  Try Signing In Again.");
  unsignFB();
};

window.savedToFB = function(pstFbStat) {
  if (pstFbStat === false) {
    alert("You are Not Signed in to Facebook!");
    unsignFB();
    google.script.run.withFailureHandler(onFailure)
      .signOutFB();
  } else {
    alert("Your Item was Posted to Facebook!");
  };
};

</script>

这篇关于在 Google Apps Script Web 应用程序中使用 Facebook API?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆