mirror of
https://github.com/neocities/neocities.git
synced 2025-04-25 01:32:36 +02:00
an unfinished start on proper paypal recurring integration
This commit is contained in:
parent
5346b7345e
commit
c4376bc580
15 changed files with 175 additions and 53 deletions
4
Gemfile
4
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
|
||||
|
|
|
@ -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
2
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'
|
||||
|
|
85
app/plan.rb
85
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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
11
migrations/057_add_paypal_data.rb
Normal file
11
migrations/057_add_paypal_data.rb
Normal 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
|
9
migrations/058_add_paypal_status.rb
Normal file
9
migrations/058_add_paypal_status.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
30
views/plan/bitcoin.erb
Normal 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 -->
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue