From c4376bc5800334d08d7ddbe211b1424de0230c06 Mon Sep 17 00:00:00 2001 From: Kyle Drake Date: Fri, 10 Apr 2015 18:15:11 -0700 Subject: [PATCH] an unfinished start on proper paypal recurring integration --- Gemfile | 4 +- Gemfile.lock | 3 + app.rb | 2 +- app/plan.rb | 85 ++++++++++++++++++++++++-- app/{stripe_webhook.rb => webhooks.rb} | 14 ++++- config.yml.template | 6 ++ config.yml.travis | 5 +- environment.rb | 7 +++ migrations/057_add_paypal_data.rb | 11 ++++ migrations/058_add_paypal_status.rb | 9 +++ tests/acceptance/plan_tests.rb | 6 +- views/plan/_pricing.erb | 6 +- views/plan/alternate.erb | 38 ------------ views/plan/bitcoin.erb | 30 +++++++++ views/welcome.erb | 2 +- 15 files changed, 175 insertions(+), 53 deletions(-) rename app/{stripe_webhook.rb => webhooks.rb} (83%) create mode 100644 migrations/057_add_paypal_data.rb create mode 100644 migrations/058_add_paypal_status.rb delete mode 100644 views/plan/alternate.erb create mode 100644 views/plan/bitcoin.erb diff --git a/Gemfile b/Gemfile index b5a3e08c..3ea81169 100644 --- a/Gemfile +++ b/Gemfile @@ -25,7 +25,9 @@ gem 'filesize' gem 'thread' gem 'scrypt' gem 'rack-cache' -gem 'rest-client' +gem 'rest-client', require: 'rest_client' +gem 'addressable' +gem 'paypal-recurring', require: 'paypal/recurring' platform :mri, :rbx do gem 'magic' # sudo apt-get install file, For OSX: brew install libmagic diff --git a/Gemfile.lock b/Gemfile.lock index e726b123..2caaea32 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -111,6 +111,7 @@ GEM netrc (0.10.3) nokogiri (1.6.3.1) mini_portile (= 0.6.0) + paypal-recurring (1.1.0) pg (0.17.1) phantomjs (1.9.7.1) poltergeist (1.5.1) @@ -233,6 +234,7 @@ PLATFORMS ruby DEPENDENCIES + addressable ago bcrypt capybara_minitest_spec @@ -252,6 +254,7 @@ DEPENDENCIES minitest minitest-reporters mocha + paypal-recurring pg poltergeist pry diff --git a/app.rb b/app.rb index bedf3554..8d53b87f 100644 --- a/app.rb +++ b/app.rb @@ -27,7 +27,7 @@ before do if request.path.match /^\/api\//i @api = true content_type :json - elsif request.path.match /^\/stripe_webhook$/ + elsif request.path.match /^\/webhooks\// # Skips the CSRF check for stripe web hooks else content_type :html, 'charset' => 'utf-8' diff --git a/app/plan.rb b/app/plan.rb index ee225d81..fbaf7d6f 100644 --- a/app/plan.rb +++ b/app/plan.rb @@ -100,11 +100,88 @@ get '/plan/thanks' do erb :'plan/thanks' end +get '/plan/bitcoin/?' do + erb :'plan/bitcoin' +end + +get '/plan/alternate/?' do + redirect '/plan/bitcoin' +end + +def paypal_recurring_hash + { + ipn_url: "#{url}/webhooks/paypal", + description: 'Neocities Supporter', + amount: Site::PLAN_FEATURES[:supporter][:price].to_s, + currency: 'USD' + } +end + +def paypal_recurring_authorization_hash + url = ENV['RACK_ENV'] == 'development' ? 'http://127.0.0.1:9292' : 'https://neocities.org' + paypal_recurring_hash.merge( + return_url: "#{url}/plan/paypal/return", + cancel_url: "#{url}/plan", + ipn_url: "#{url}/webhooks/paypal" + ) +end + +get '/plan/paypal' do + require_login + + hash = paypal_recurring_authorization_hash + + if current_site.paypal_token + hash.merge! token: current_site.paypal_token + end + + ppr = PayPal::Recurring.new hash + + paypal_response = ppr.checkout + + redirect paypal_response.checkout_url if paypal_response.valid? +end + +get '/plan/paypal/return' do + require_login + + if params[:TOKEN].nil? || params[:PAYERID].nil? + flash[:error] = 'Unknown error, could not complete the request. Please contact Neocities support.' + end + + ppr = PayPal::Recurring.new(paypal_recurring_hash.merge( + token: params[:TOKEN], + payer_id: params[:PAYERID] + )) + + paypal_response = ppr.request_payment + unless paypal_response.approved? && paypal_response.completed? + flash[:error] = 'Unknown error, could not complete the request. Please contact Neocities support.' + redirect '/plan' + end + + ppr = PayPal::Recurring.new(paypal_recurring_authorization_hash.merge( + frequency: 1, + token: params[:TOKEN], + period: :monthly, + reference: current_site.id.to_s, + payer_id: params[:PAYERID], + start_at: Time.now, + failed: 3, + outstanding: :next_billing + )) + + paypal_response = ppr.create_recurring_profile + + current_site.paypal_token = params[:TOKEN] + current_site.paypal_profile_id = paypal_response.profile_id + current_site.paypal_active = true + current_site.save_changes validate: false + + redirect '/plan/thanks-paypal' +end + get '/plan/thanks-paypal' do require_login erb :'plan/thanks-paypal' end - -get '/plan/alternate/?' do - erb :'/plan/alternate' -end diff --git a/app/stripe_webhook.rb b/app/webhooks.rb similarity index 83% rename from app/stripe_webhook.rb rename to app/webhooks.rb index f46b7934..9b964a30 100644 --- a/app/stripe_webhook.rb +++ b/app/webhooks.rb @@ -1,4 +1,16 @@ -post '/stripe_webhook' do +post '/webhooks/paypal' do + EmailWorker.perform_async({ + from: 'web@neocities.org', + to: 'errors@neocities.org', + subject: "[Neocities Paypal Webhook] Received a Webhook from Paypal", + body: params.inspect, + no_footer: true + }) + + 'ok' +end + +post '/webhooks/stripe' do event = JSON.parse request.body.read if event['type'] == 'customer.created' username = event['data']['object']['description'].split(' - ').first diff --git a/config.yml.template b/config.yml.template index 2cd830cc..00045723 100644 --- a/config.yml.template +++ b/config.yml.template @@ -12,6 +12,9 @@ development: proxy_pass: 'somethinglongandrandom' email_unsubscribe_token: 'somethingrandom' logs_path: /path/to/nginx/logs + paypal_api_username: derp + paypal_api_password: ing + paypal_api_signature: tonz test: database: 'postgres://neocities@localhost/neocities_test' database_pool: 1 @@ -25,3 +28,6 @@ test: ip_hash_salt: "400$8$1$fc21863da5d531c1" proxy_pass: 'somethinglongandrandom' email_unsubscribe_token: 'somethingrandom' + paypal_api_username: derp + paypal_api_password: ing + paypal_api_signature: tonz diff --git a/config.yml.travis b/config.yml.travis index 627467e9..21d2a2c1 100644 --- a/config.yml.travis +++ b/config.yml.travis @@ -6,4 +6,7 @@ recaptcha_private_key: '5678' phantomjs_url: - http://localhost:8910 ip_hash_salt: "400$8$1$fc21863da5d531c1" -email_unsubscribe_token: "somethingrandomderrrrp" \ No newline at end of file +email_unsubscribe_token: "somethingrandomderrrrp" +paypal_api_username: derp +paypal_api_password: ing +paypal_api_signature: tonz diff --git a/environment.rb b/environment.rb index ccff05f4..67ac5bdd 100644 --- a/environment.rb +++ b/environment.rb @@ -131,3 +131,10 @@ if ENV['RACK_ENV'] != 'development' # Sass::Plugin.options[:never_update] = true Sass::Plugin.options[:full_exception] = false end + +PayPal::Recurring.configure do |config| + config.sandbox = false + config.username = $config['paypal_api_username'] + config.password = $config['paypal_api_password'] + config.signature = $config['paypal_api_signature'] +end diff --git a/migrations/057_add_paypal_data.rb b/migrations/057_add_paypal_data.rb new file mode 100644 index 00000000..684d637a --- /dev/null +++ b/migrations/057_add_paypal_data.rb @@ -0,0 +1,11 @@ +Sequel.migration do + up { + DB.add_column :sites, :paypal_profile_id, String + DB.add_column :sites, :paypal_token, String + } + + down { + DB.drop_column :sites, :paypal_profile_id + DB.drop_column :sites, :paypal_token + } +end diff --git a/migrations/058_add_paypal_status.rb b/migrations/058_add_paypal_status.rb new file mode 100644 index 00000000..12391a22 --- /dev/null +++ b/migrations/058_add_paypal_status.rb @@ -0,0 +1,9 @@ +Sequel.migration do + up { + DB.add_column :sites, :paypal_active, :boolean, default: false + } + + down { + DB.drop_column :sites, :paypal_active + } +end diff --git a/tests/acceptance/plan_tests.rb b/tests/acceptance/plan_tests.rb index 650b4731..77a7f70d 100644 --- a/tests/acceptance/plan_tests.rb +++ b/tests/acceptance/plan_tests.rb @@ -19,6 +19,10 @@ describe '/plan' do StripeMock.stop end + it 'should work for paypal' do + + end + it 'should work for fresh signup' do visit '/plan' fill_in 'Card Number', with: '4242424242424242' @@ -41,4 +45,4 @@ describe '/plan' do mail = Mail::TestMailer.deliveries.first mail.subject.must_match "You've become a supporter" end -end \ No newline at end of file +end diff --git a/views/plan/_pricing.erb b/views/plan/_pricing.erb index 6eda3f0f..f7d19af1 100644 --- a/views/plan/_pricing.erb +++ b/views/plan/_pricing.erb @@ -1,7 +1,3 @@ -<% - -%> -
<% if request.path.match /\/welcome/ %>
@@ -83,7 +79,7 @@ <%== plan_pricing_button :supporter %> <% end %>