Facebook开发如何时时追蹤安装-退出你的应用程式的使用
看到 Robert Shedd 的 这篇部落格 ,提到这个问题,整理一下分享给大家,相关的 code 也是引用自该文章。
基本问题 -- 因为 facebook 没给安装你应用的用户清单,没办法精準掌握现有用户
这里假设你已经用 RoR+Facebooker 开发了几个应用,如果还没,可以阅读:
那幺,用 facebooker 开发好了一个 ROR 在 facebook 上的应用后,如果想知道目前某人现在是否安装了你的程式,当他连上有建立 Session 的时候,我们用 User#has_added_app 可以知道他是否安装了程式。如果把他的 user id 存在 local 的资料库里,那幺你就可以知道目前所有"安装了"你应用程式的使用者了。
不过,如果使用者在某个时间删除掉了你的应用程式,也就是说他退出了,由于退出时没有建立与 ap 间的 session,我们不能用 has_added_app 来了解状况,并删除 local 资料库的资料。使用者有进有出,时间久了,你的 local 资料库上的资料就不準确了。若有做排名的列表,就可能出现幽灵人,明明已经没装你的应用,却仍高挂第一名。
解决方法 -- 使用 post_authorize 与 post_deauthorize
针对这样的需求,facebook 提供了 post_authorize 与 post_deauthorize 两个 callback,注册了应用跟移除应用都可以通知我们的 ap 一声,在这个地方做些事情,那幺我们就能确保数据的一致性了。
首先,Robert 建议另开一个 Controller,另外就是要注意要确认 authenticity token,程式码範例如下:
class CallbacksController < ApplicationController skip_before_filter :ensure_app_installed, :except => :post_authorize skip_before_filter :verify_authenticity_token def post_authorize if request.post? #做些事情,例如存资料库 render :nothing => true end end def post_deauthorize if request.post? #做些事情,例如删除资料 render :nothing => true end endend
进阶注意-进一步确认加入/退出请求实际来自 Facebook 平台
以上程式码已经可以了,可以解决使用者新增与退出应用时,我们能精準掌握他的状态的问题了。不过,我们仍得注意另一个问题,就是这个动作是否来自 facebook 平台,免得被其他人透过其他方式触发了。在上述的程式码里加上这段检查,就变成了:
class CallbacksController < ApplicationController skip_before_filter :ensure_app_installed, :except => :post_authorize skip_before_filter :verify_authenticity_token def post_authorize if request.post? if verify_uninstall_signature #将使用者的 has_app 设成 1 end end render :nothing => true end def post_deauthorize if request.post? if verify_uninstall_signature #把使用者的 has_app 设成 0 end end render :nothing => true end private #参考了 http://wiki.developers.facebook.com/index.php/Post-Remove_URL def verify_uninstall_signature signature = '' keys = params.keys.sort keys.each do |key| next if key == 'fb_sig' next unless key.include? key_name = key.gsub signature += key_name signature += '=' signature += params[key] end signature += FACEBOOK_YAML['secret_key'] calculated_sig = Digest::MD5.hexdigest if calculated_sig != params[:fb_sig] logger.warn "\nWARNING :: potential spoofing :: expected signatures did not match" logger.info "\nSignature:: #{params[:fb_sig]}" logger.info "\nSignature String:: #{signature}" logger.info "\nMD5 Hashed Sig :: #{calculated_sig}" #check to see if ip variables are nil if not request.env['HTTP_X_FORWARDED_FOR'].nil? and not request.env['HTTP_X_REAL_IP'].nil? ip = request.env['HTTP_X_FORWARDED_FOR'] || request.env['HTTP_X_REAL_IP'] else ip = request.remote_ip end logger.info "\nRemote IP :: #{ip}" return false else #logger.warn "\n\nSUCCESS!! Signatures matched.\n" end return true endend
其中要注意的是关于 FACEBOOK_YAML[‘secret_key’] 的这行,密码金钥要定义在 environment.rb:
#load facebooker configuration for usage facebook_config = File.join FACEBOOK_YAML = YAML::load).result)[RAILS_ENV]
这样,就可以準确掌握你的应用程式中真正的活跃者了!Happy Coding!