Skip to content

Commit

Permalink
Refactor env vars to be friendlier to local dev
Browse files Browse the repository at this point in the history
It seems like we don't need to split out client-environment from
server-environment in docker-compose files (production hasn't been doing
it this whole time) because the env vars don't get passed down to the
client unless they're explicitly used (via `process.env`), so there's no
risk to leaking secrets.
  • Loading branch information
glacials committed Dec 6, 2020
1 parent e09a3d9 commit 0089d7a
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 54 deletions.
15 changes: 12 additions & 3 deletions .envrc.example
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,26 @@ export GOOGLE_CLIENT_SECRET=changeme
export PATREON_CLIENT_ID=changeme
export PATREON_CLIENT_SECRET=changeme

# PayPal
# - Required for PayPal payments to work (even in test mode)
# - Create one at https://developer.paypal.com/developer/applications/create
# - Make a webhook for /api/webhooks/paypal subscribed to "Billing subscription cancelled"
# - Create a Subscription Plan at https://www.paypal.com/billing/plans and set its plan ID as PAYPAL_PLAN_ID in docker-compose.yml
export PAYPAL_CLIENT_ID=changeme
export PAYPAL_CLIENT_SECRET=changeme

# Splits.io
# - Required for some JavaScript->Rails API calls to work, including WebSockets features like races
# - This should not need changing if you have run `make seed`
# - Create one at http://localhost:3000/settings/applications/new
# - Set redirect URI to http://localhost:3000/auth/splitsio/callback
export SPLITSIO_CLIENT_ID=changeme
export SPLITSIO_CLIENT_SECRET=changeme
export SPLITSIO_CLIENT_ID=beep
export SPLITSIO_CLIENT_SECRET=boop

# Stripe
# - Required for Stripe payments to work (even in test mode)
# - Create one at https://stripe.com/
# - Create a Subscription with two Plans and set their plan IDs in docker-compose.yml
# - Create a Subscription with one Plan and set its plan ID as STRIPE_PLAN_ID_TIER3 in docker-compose.yml
# - Make a webhook for /api/webhooks/stripe subscribed to customer.subscription.deleted and checkout.session.completed
export STRIPE_PUBLISHABLE_KEY=changeme
export STRIPE_SECRET_KEY=changeme
Expand Down
47 changes: 23 additions & 24 deletions app/javascript/paypal.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { loadScript } from '@paypal/paypal-js';
import { loadScript } from '@paypal/paypal-js'

document.addEventListener("turbolinks:load", function() {
// Keeps loadScript from only executing on /subscriptions
if ($('#paypal-button-container').length < 1) {
return false;
document.addEventListener("turbolinks:load", function () {
if (!document.getElementById('paypal-button-container')) {
return false
}

loadScript({
Expand All @@ -14,41 +13,41 @@ document.addEventListener("turbolinks:load", function() {
}).then(() => {
const buttons = paypal.Buttons({
style: {
shape: 'rect',
color: 'gold',
layout: 'horizontal',
label: 'subscribe'
shape: 'rect',
color: 'gold',
layout: 'horizontal',
label: 'subscribe'
},
createSubscription: function(data, actions) {
createSubscription: function (_, actions) {
return actions.subscription.create({
plan_id: process.env.PAYPAL_PLAN_ID,
application_context: {
shipping_preference: 'NO_SHIPPING'
}
});
})
},
onApprove: function(data) {
onApprove: function (data) {
fetch('/payments/paypal-create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) { throw new Error('Subscription failed'); }
return response.json();
})
.then(data => {
Turbolinks.visit(data.location);
});
.then(response => {
if (!response.ok) { throw new Error('Subscription failed') }
return response.json()
})
.then(data => {
Turbolinks.visit(data.location)
})
}
});
})

buttons.render('#paypal-button-container').catch((err) => {
console.warn(
"Warning - Caught an error when attempting to render", err
);
});
});
});
)
})
})
})
16 changes: 7 additions & 9 deletions config/application.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require_relative 'boot'
require_relative "boot"

require 'rails/all'
require "rails/all"

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Expand All @@ -11,8 +11,8 @@ class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.0

config.autoload_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join("lib")
config.eager_load_paths << Rails.root.join("lib")

config.action_controller.allow_forgery_protection = false
config.active_job.queue_adapter = :delayed_job
Expand All @@ -22,14 +22,12 @@ class Application < Rails::Application
end

config.to_prepare do
Doorkeeper::AuthorizationsController.layout 'application'
Doorkeeper::AuthorizationsController.layout "application"
end

config.action_cable.disable_request_forgery_protection = true
config.action_cable.url = '/api/cable'
config.action_cable.mount_path = '/api/cable'

Webpacker::Compiler.env['STRIPE_PUBLISHABLE_KEY'] = ENV['STRIPE_PUBLISHABLE_KEY']
config.action_cable.url = "/api/cable"
config.action_cable.mount_path = "/api/cable"

config.active_storage.variant_processor = :vips
end
Expand Down
3 changes: 2 additions & 1 deletion docker-compose-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ x-environment:
- STRIPE_WEBHOOK_SECRET
- TWITCH_CLIENT_ID
- TWITCH_CLIENT_SECRET
- PAYPAL_API_HOST=api-m.paypal.com
- PAYPAL_CLIENT_ID
- PAYPAL_SECRET_KEY
- PAYPAL_CLIENT_SECRET
- PAYPAL_PLAN_ID=P-8X852520X76298909L7B74BY
x-logging:
&default-logging
Expand Down
9 changes: 3 additions & 6 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,10 @@ x-server-environment:
- STRIPE_WEBHOOK_SECRET
- TWITCH_CLIENT_ID
- TWITCH_CLIENT_SECRET
- PAYPAL_API_HOST=api-m.sandbox.paypal.com
- PAYPAL_CLIENT_ID
- PAYPAL_SECRET_KEY
- PAYPAL_CLIENT_SECRET
- PAYPAL_PLAN_ID=P-86R46997GH219170TL7DOHCA
x-client-environment:
&client-environment
- SPLITSIO_CLIENT_ID
- STRIPE_PUBLISHABLE_KEY=pk_test_8XH713ExTipOnBebjfsHHffm
x-logging:
&default-logging
driver: json-file
Expand Down Expand Up @@ -89,7 +86,7 @@ services:
webpacker:
<<: *app
command: bash -c "ruby bin/webpack-dev-server"
environment: *client-environment
environment: *server-environment
logging: *default-logging
ports:
- 3035:3035
Expand Down
21 changes: 10 additions & 11 deletions lib/paypal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@

class Paypal
class Subscribe
# Sandbox url
# UNSUB_BASE_URL = "https://api-m.sandbox.paypal.com/v1/billing/subscriptions"
UNSUB_BASE_URL = "https://api-m.paypal.com/v1/billing/subscriptions"
AUTH = { username: ENV["PAYPAL_CLIENT_ID"], password: ENV["PAYPAL_SECRET_KEY"] }
AUTH = { username: ENV["PAYPAL_CLIENT_ID"], password: ENV["PAYPAL_CLIENT_SECRET"] }

# check_subscription(subscription_id: String)
# Calls PayPal API to find a subscription ID to ensure it is valid.
def self.check_subscription(data)
HTTParty.get(URI.parse("#{UNSUB_BASE_URL}/#{data["subscriptionID"]}"),
HTTParty.get(
URI::HTTPS.build(host: ENV["PAYPAL_API_HOST"], path: "/v1/billing/subscriptions/#{data["subscriptionID"]}"),
basic_auth: AUTH,
headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json' }
headers: { "Content-Type" => "application/json", "Accept" => "application/json" },
)
end

Expand All @@ -35,21 +33,21 @@ def self.create(data, user)
stripe_plan_id: ENV["PAYPAL_PLAN_ID"],
stripe_subscription_id: data["subscriptionID"],
stripe_session_id: data["orderID"],
stripe_payment_intent_id: data["billingToken"]
stripe_payment_intent_id: data["billingToken"],
)

subscription
rescue => e
{
error: e.inspect,
response: response.inspect,
message: "Failed to create user subscription for #{user&.id}"
message: "Failed to create user subscription for #{user&.id}",
}
end
else
{
error: "Failed to find valid subscription",
response: response.inspect
response: response.inspect,
}
end
end
Expand All @@ -65,9 +63,10 @@ def self.cancel_all(user)

subscriptions.each do |sub|
if sub.stripe_subscription_id.present?
response = HTTParty.post(URI.parse("#{UNSUB_BASE_URL}/#{sub.stripe_subscription_id}/cancel"),
response = HTTParty.post(
URI::HTTPS.build(host: ENV["PAYPAL_API_HOST"], path: "/v1/billing/subscriptions/#{data["subscriptionID"]}/cancel"),
basic_auth: AUTH,
headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json' }
headers: { "Content-Type" => "application/json", "Accept" => "application/json" },
)
end
sub.update(canceled_at: Time.now.utc) if sub.canceled_at.nil?
Expand Down

0 comments on commit 0089d7a

Please sign in to comment.