an unfinished start on proper paypal recurring integration

This commit is contained in:
Kyle Drake 2015-04-10 18:15:11 -07:00
parent 5346b7345e
commit c4376bc580
15 changed files with 175 additions and 53 deletions

View file

@ -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

View file

@ -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

2
app.rb
View file

@ -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'

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -6,4 +6,7 @@ recaptcha_private_key: '5678'
phantomjs_url:
- http://localhost:8910
ip_hash_salt: "400$8$1$fc21863da5d531c1"
email_unsubscribe_token: "somethingrandomderrrrp"
email_unsubscribe_token: "somethingrandomderrrrp"
paypal_api_username: derp
paypal_api_password: ing
paypal_api_signature: tonz

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
end

View file

@ -1,7 +1,3 @@
<%
%>
<section class="section plans">
<% if request.path.match /\/welcome/ %>
<div class="txt-Center"><img src="/img/heartcat.png"></div>
@ -83,7 +79,7 @@
<%== plan_pricing_button :supporter %>
<% end %>
<ul>
<li><strong><%= Site::PLAN_FEATURES[:supporter][:space].to_space_pretty %></strong> storage</li>
<li><strong><%= (Site::PLAN_FEATURES[:supporter][:space] / (10**6)).to_comma_separated %> MB</strong> storage</li>
<li><strong><%= Site::PLAN_FEATURES[:supporter][:bandwidth].to_space_pretty %></strong> bandwidth</li>
</ul>
<ul>

View file

@ -1,38 +0,0 @@
<style>
h3 { margin-top: 20px; }
</style>
<div class="header-Outro">
<div class="row content single-Col">
<h1>Alternate Payment Options</h1>
<h3 class="subtitle">Not everyone has a credit card, so we support many different types of payment.</h3>
</div>
</div>
<div class="content single-Col misc-page txt-Center">
<article>
<section>
<h2>PayPal</h2>
<p>For people that can't use a Credit Card, we support PayPal for supporter upgrades.</p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="DFQBR5LNS3NW8">
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_subscribeCC_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_US/i/scr/pixel.gif" width="1" height="1">
</form>
<h2>The Bitcoin Lifer Plan</h2>
<p>
We don't have a good way to charge recurring with Bitcoin. So instead, we've put together the <strong>lifer plan</strong>. Basically, if you send us three years worth of supporter ($180USD), we'll never charge you again for the supporter upgrade, and you'll basically get it forever!
</p>
<p>Be sure to <a href="/contact">contact us</a> after sending with the transaction ID so we can confirm and upgrade your account.</p>
<p><img src="/img/bitcoin.png"></p>
<p><b>1MPYyfoWK8CkAzhLzLLtZGa9dwEGT5dm2T</b></p>
<h2>Gratipay:</h2>
<script data-gratipay-username="neocities" src="//gttp.co/v1.js"></script>
</section>
</article>
</div> <!-- end .content -->

30
views/plan/bitcoin.erb Normal file
View file

@ -0,0 +1,30 @@
<style>
h3 { margin-top: 20px; }
</style>
<div class="header-Outro">
<div class="row content single-Col">
<h1>Bitcoin</h1>
<h3 class="subtitle">Yes, Neocities accepts Bitcoin!</h3>
</div>
</div>
<div class="content single-Col misc-page txt-Center">
<article>
<section>
<h2>The Bitcoin Homesteader Plan</h2>
<p>
We don't have a good way to charge recurring with Bitcoin (that adheres to Bitcoin's decentralized principles). So instead, we've put together a <strong>lifer plan</strong>. Basically, if you send us <strong>$50</strong> worth of BTC, we'll never charge you again for the supporter upgrade, and you'll basically get it forever!
</p>
<p>Be sure to <a href="/contact">contact us</a> after sending with the transaction ID so we can confirm and upgrade your account.</p>
<p>
We don't cash out the Bitcoin. Many of our providers accept Bitcoin, and we use it to pay them.
</p>
<p><img src="/img/bitcoin.png"></p>
<p><b>1MPYyfoWK8CkAzhLzLLtZGa9dwEGT5dm2T</b></p>
</section>
</article>
</div> <!-- end .content -->

View file

@ -96,7 +96,7 @@
<a href="/" class="btn-Action" onclick="$('#upgradeForm').submit(); return false">
Upgrade for $<%= Site::PLAN_FEATURES[:supporter][:price] %>/mo
</a>
or pay with <a href="/plan/alternate/">PayPal</a> or <a href="/plan/alternate/">Bitcoin</a>
or pay with <strong><a href="/plan/paypal">PayPal</a></strong> or <strong><a href="/plan/bitcoin">Bitcoin</a></strong>
</div>
</div>
</div>