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...
Asked
Active
Viewed 1,336 times
13
-
2Okay so I have my Ruby On Rails version working, so I'll post a copy of it in here shortly if anyone's interested. Then maybe I'll look to gemify it, if that seems to make sense. – Richard Jordan Feb 04 '11 at 00:33
-
1Hey Richard, did you ever post a copy of your working Rails Facebook credits app? I'm interested in looking it over. Thanks! – Tim Feb 12 '11 at 19:00
-
No Tim, sorry, completely forgot. I'll get to it this week. If you don't see it here shortly just message me directly. – Richard Jordan Mar 28 '11 at 02:00
1 Answers
14
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' :-)

Richard Jordan
- 8,066
- 3
- 39
- 45
-
hai.. I like to use facebook credits api for my rails 3 application. Can share the code of the views as well. So that I can understand how flow begins. – Amal Kumar S Jul 15 '11 at 13:31
-
Hi - I'll be happy to share any of it :-) ...I'll have to dig out what I did in the views (not working on this application at the moment) so please be patient and I'll post... alternatively feel free to message me directly on here and chase me for the code :-) ...R – Richard Jordan Jul 19 '11 at 19:59
-
-
done... also you probably don't need openssl any more because with Rails 3.1 you can get ssl baked in :-) ...oh and if these answers are helpful to you Amal please vote the answer up - it means something to me to get an up arrow click :-) – Richard Jordan Jul 26 '11 at 22:02
-
Hey, I'm at the point of the elsif status == 'settled' and the redirect to '/lots', which sends "order_details" parameters to a #create method (post). After it creates a new @lots object, it redirects ANOTHER post to the lots/:ID path. Did u run into this problem and if so How did you solve this? – JZ. Aug 19 '11 at 01:24
-
Hi... sorry for not responding sooner - I hadn't noticed your comment... I don't have this code live anywhere right now, as I built a prototype of something which I decided not to go live with. I am going to build the whole thing from scratch again (hopefully better and worthy of launch) this weekend at the TechCrunch Disrupt hackathon, so I'll almost certainly see the problem you mention there and if/when I do I'll ping you my answer. – Richard Jordan Sep 07 '11 at 23:18