Created
May 22, 2012 11:40
-
-
Save chrismdp/2768532 to your computer and use it in GitHub Desktop.
Paypal IPN integration in about 30 lines of Sinatra.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/app/account.rb b/app/account.rb | |
index a108685..c89ad34 100644 | |
--- a/app/account.rb | |
+++ b/app/account.rb | |
@@ -1,4 +1,22 @@ | |
+require 'open-uri' | |
+ | |
module Sol | |
+ class Url | |
+ def self.get(url) | |
+ open(url).read | |
+ end | |
+ end | |
+ | |
+ class PaypalVerifier | |
+ def initialize(query) | |
+ @query = query | |
+ end | |
+ def verified? | |
+ url = "https://www.paypal.com/cgi-bin/webscr?cmd=_notify-validate&#{@query}" | |
+ Url.get(url) == "VERIFIED" | |
+ end | |
+ end | |
+ | |
class AccountApp < Sinatra::Application | |
get '/?' do | |
env['warden'].authenticate! | |
@@ -26,6 +44,18 @@ module Sol | |
redirect '/' | |
end | |
+ post '/ipn/?' do | |
+ return "FAILED VERIFICATION" unless (PaypalVerifier.new(request.env["rack.input"].read).verified?) | |
+ return "PAYMENT NOT COMPLETE" unless (params[:payment_status] == 'Completed') | |
+ if (@account = Account.where(:username => params[:option_selection1]).first) | |
+ @account.update_attribute(:purchased_at, Time.now) | |
+ Pony.mail(:to => @account.email, :subject => "Your Sol Trader account is activated", :body => erb(:activation_email, :layout => false)) | |
+ "OK" | |
+ else | |
+ "NOT FOUND" | |
+ end | |
+ end | |
+ | |
post '/purchased' do | |
if params[:secret] == Build::SECRET | |
@account = Account.where(:username => params[:username]).first | |
diff --git a/spec/integration/recording_purchase_spec.rb b/spec/integration/recording_purchase_spec.rb | |
index 8380889..debb21e 100644 | |
--- a/spec/integration/recording_purchase_spec.rb | |
+++ b/spec/integration/recording_purchase_spec.rb | |
@@ -40,3 +40,56 @@ describe "Recording purchases" do | |
post '/purchased', :username => 'username', :secret => Build::SECRET | |
end | |
end | |
+ | |
+describe "Paypal IPN" do | |
+ include Rack::Test::Methods | |
+ | |
+ def app | |
+ Sol::AccountApp | |
+ end | |
+ | |
+ let(:fields) {{ | |
+ :email => 'foo@example.com', | |
+ :password => 'password', | |
+ :password_confirmation => 'password', | |
+ :username => 'username' | |
+ }} | |
+ | |
+ before do | |
+ Account.create!(fields) | |
+ Pony.stub(:mail) | |
+ Sol::Url.stub(:get => "VERIFIED") | |
+ end | |
+ | |
+ it "verifies that the paypal address is genuine" do | |
+ Sol::Url.should_receive(:get).with("https://www.paypal.com/cgi-bin/webscr?cmd=_notify-validate&test=ipn_query_string").and_return("VERIFIED") | |
+ post '/ipn', :test => 'ipn_query_string' | |
+ end | |
+ | |
+ it "doesn't do anything if the account does not verify" do | |
+ Sol::Url.stub(:get => "INVALID") | |
+ post '/ipn', 'ipn_query_string' | |
+ Account.first.should_not be_game_owner | |
+ Pony.should_not_receive(:mail) | |
+ end | |
+ | |
+ it "records purchases for usernames" do | |
+ post '/ipn', :option_selection1 => fields[:username], :payment_status => "Completed" | |
+ Account.first.should be_game_owner | |
+ end | |
+ | |
+ it "does not record purchases for unknown username" do | |
+ post '/ipn', :option_selection1 => 'unknown' | |
+ Account.first.should_not be_game_owner | |
+ end | |
+ | |
+ it "does not record purchases unless the payment_status is Completed" do | |
+ post '/ipn', :option_selection1 => fields[:username] | |
+ Account.first.should_not be_game_owner | |
+ end | |
+ | |
+ it "sends email to the purchaser" do | |
+ Pony.should_receive(:mail).with(hash_including(:to => Account.first.email)) | |
+ post '/ipn', :option_selection1 => fields[:username], :payment_status => "Completed" | |
+ end | |
+end | |
diff --git a/views/account.erb b/views/account.erb | |
index c478f26..7eface2 100644 | |
--- a/views/account.erb | |
+++ b/views/account.erb | |
@@ -68,6 +68,7 @@ | |
<input type="hidden" name="no_shipping" value="1"> | |
<input type="hidden" name="rm" value="1"> | |
<input type="hidden" name="return" value="http://soltrader.net/success"> | |
+ <input type="hidden" name="notify_url" value="http://soltrader.net/account/ipn"> | |
<input type="hidden" name="bn" value="PP-BuyNowBF:btn_buynow_LG.gif:NonHosted"> | |
<input type="image" src="https://www.paypalobjects.com/en_GB/i/btn/btn_buynow_LG.gif" border="0" name="submit" alt="PayPal — The safer, easier way to pay online."> | |
<img alt="" border="0" src="https://www.paypalobjects.com/en_GB/i/scr/pixel.gif" width="1" height="1"> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment