I am wanting to implement Facebook Credits in my Facebook app. Does anyone know of a version of the Facebook Credits sample app available in Ruby on Rails? Has anybody made a gem for this yet? If I find one I'll link below...
Here is my code taking the FB example and RORing it:
require 'facebook_signed_request.rb'
class FacebookCreditsController < ApplicationController
skip_before_filter :verify_authenticity_token
layout nil
def index
facebook_request = FacebookSignedRequest.new(request.params['signed_request'])
data = { "content" => {} }
# handle invalid request
if !facebook_request.valid?
return
end
signed_request = facebook_request.signed_request
# handle invalid signed request
if signed_request.nil?
return
end
method = request.params['method']
order_id = request.params['order_id']
# second state response from facebook
if method == 'payments_status_update'
status = request.params['status']
if status == 'placed'
next_state = 'settled'
data['content']['status'] = next_state
elsif status == 'settled'
redirect_to '/lots'
return
end
# compose returning data array_change_key_case
data['content']['order_id'] = order_id
# first stage response from facebook
elsif method == 'payments_get_items'
order_info = request.params['order_info']
item = JSON.parse(order_info)
item['price'] = item['price'].to_i
# for url fields, if not prefixed by http://, prefix them
url_key = [ 'product_url', 'image_url' ]
url_key.each do |key|
if item[key][0..6] != 'http://'
item[key] = "http://#{item[key]}"
end
end
# if payload['test_mode']
if request.params['test_mode']
update_keys = ['title', 'description']
update_keys.each do |key|
item[key] = '[Test Mode] ' + item[key]
end
end
data['content'] = [item]
end
data['method'] = method
render :json => data
end
end
Then in addition to this there is:
require 'base64'
require 'json'
require 'openssl'
class FacebookSignedRequest
attr_reader :signed_request
def initialize(signed_request)
@signed_request = signed_request
end
def base64_url_decode str
encoded_str = str.gsub('-','+').gsub('_','/')
encoded_str += '=' while !(encoded_str.size % 4).zero?
Base64.decode64(encoded_str)
end
def valid?
# TODO: move it to some configuration
secret = " << my secret is here >>"
# decode data
encoded_sig, payload = signed_request.split('.')
sig = base64_url_decode(encoded_sig).unpack("H*")[0]
data = JSON.parse base64_url_decode(payload)
if data['algorithm'].to_s.upcase != 'HMAC-SHA256'
# Rails.logger.error 'Unknown algorithm. Expected HMAC-SHA256'
return false
end
#check sig
expected_sig = OpenSSL::HMAC.hexdigest('sha256', secret, payload)
if expected_sig != sig
# Rails.logger.error 'Bad Signed JSON signature!'
return false
end
data
end
I don't know if this helps anyone else but it's all working for me. Sorry for taking so long to remember to come back and post my working code...
View related code as requested:
#view
<%= javascript_include_tag "premium_signup" %>
<script type="text/javascript">
$(document).ready(function() {
$('#premium_signup_button').click(function() {
signupAsPremiumMember('Premium Membership', 'Create unlimited auctions with no extra charge at all for 1 year.', "1", '', '');
});
});
</script>
...
<button id="premium_signup_button">Signup as a premium member</button>
#premium_signup.js
function signupAsPremiumMember(title, desc, price, imageURL, productURL) {
var order_info = {
"title": title,
"description": desc,
"price": price,
"image_url": imageURL,
"product_url": productURL
};
var payload = {
"method": 'pay',
"order_info": order_info,
"purchase_type": 'item'
};
console.log(FB.ui(payload, facebookPurchaseCompletionCallback));
}
function facebookPurchaseCompletionCallback(data) {
if (data['order_id']) {
console.log(data['order_id']);
}
else if (data['error_code']) {
console.log(data['error_code']);
}
else {
console.log("failed");
}
}
#in the layout
#in head
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="http://connect.facebook.net/en_US/all.js"></script>
<%= javascript_include_tag 'application' %>
#in body
<div id="fb-root"></div>
<script>
FB.init({
appId : '############',
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
Now all of this is coming from a guy who sat down and learned to program in Ruby On Rails with as little supporting Javascript knowledge as I can get away with, in about 12 weeks last year with a few more weeks thrown in this year for good measure. I say that by way of caution - the code I've posted might be garbage... but it works :-)
And if anyone actually finds any of this useful a VOTE UP on the answer would be appreciated - just sayin' :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With