upgrades: factor out Stripe integration.

Factor out the Stripe code from the UserUpgrade class. Introduce a new
PaymentTransaction abstract class that represents a payment with some
payment processor, and a PaymentTransaction::Stripe class that
implements transactions with Stripe.

Note that we can't completely eliminate Stripe even though we no longer
accept payments with it because we still need to be able to look up old
payments in Stripe.
This commit is contained in:
evazion
2022-05-06 22:26:52 -05:00
parent 0d4c8baed8
commit 449fd6c49c
9 changed files with 293 additions and 214 deletions

View File

@@ -9,8 +9,8 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
StripeMock.stop
end
def post_webhook(*args, metadata: {}, payment_status: "paid")
skip unless UserUpgrade.enabled?
def post_stripe_webhook(*args, metadata: {}, payment_status: "paid")
skip unless PaymentTransaction::Stripe.enabled?
event = StripeMock.mock_webhook_event(*args, payment_status: payment_status, metadata: metadata)
signature = generate_stripe_signature(event)
headers = { "Stripe-Signature": signature }
@@ -22,7 +22,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
# https://stripe.com/docs/webhooks/signatures
def generate_stripe_signature(event)
time = Time.now
secret = UserUpgrade.stripe_webhook_secret
secret = Danbooru.config.stripe_webhook_secret
signature = Stripe::Webhook::Signature.compute_signature(time, event.to_json, secret)
Stripe::Webhook::Signature.generate_header(time, signature, scheme: Stripe::Webhook::Signature::EXPECTED_SCHEME)
end
@@ -58,7 +58,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
context "for a payment_intent.created event" do
should "work" do
post_webhook("payment_intent.created")
post_stripe_webhook("payment_intent.created")
assert_response 200
end
@@ -68,7 +68,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
context "for completed event with an unpaid payment status" do
should "not upgrade the user" do
@user_upgrade = create(:self_gold_upgrade)
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id }, payment_status: "unpaid")
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id }, payment_status: "unpaid")
assert_response 200
assert_equal("processing", @user_upgrade.reload.status)
@@ -80,7 +80,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
context "to Gold" do
should "upgrade the user" do
@user_upgrade = create(:self_gold_upgrade)
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
assert_response 200
assert_equal("complete", @user_upgrade.reload.status)
@@ -91,7 +91,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
context "to Platinum" do
should "upgrade the user" do
@user_upgrade = create(:self_platinum_upgrade)
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
assert_response 200
assert_equal("complete", @user_upgrade.reload.status)
@@ -102,7 +102,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
context "from Gold to Platinum" do
should "upgrade the user" do
@user_upgrade = create(:self_gold_to_platinum_upgrade)
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
assert_response 200
assert_equal("complete", @user_upgrade.reload.status)
@@ -115,7 +115,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
context "to Gold" do
should "upgrade the user" do
@user_upgrade = create(:gift_gold_upgrade)
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
assert_response 200
assert_equal("complete", @user_upgrade.reload.status)
@@ -126,7 +126,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
context "to Platinum" do
should "upgrade the user" do
@user_upgrade = create(:gift_platinum_upgrade)
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
assert_response 200
assert_equal("complete", @user_upgrade.reload.status)
@@ -137,7 +137,7 @@ class WebhooksControllerTest < ActionDispatch::IntegrationTest
context "from Gold to Platinum" do
should "upgrade the user" do
@user_upgrade = create(:gift_gold_to_platinum_upgrade)
post_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
assert_response 200
assert_equal("complete", @user_upgrade.reload.status)

View File

@@ -3,11 +3,11 @@ StripeMock.webhook_fixture_path = "test/fixtures/stripe-webhooks"
module StripeTestHelper
def mock_stripe!
setup do
StripeMock.start unless UserUpgrade.enabled?
StripeMock.start unless PaymentTransaction::Stripe.enabled?
end
teardown do
StripeMock.stop unless UserUpgrade.enabled?
StripeMock.stop unless PaymentTransaction::Stripe.enabled?
end
end
end

View File

@@ -44,7 +44,7 @@ class UserUpgradeTest < ActiveSupport::TestCase
context "for a gifted upgrade" do
context "to Gold" do
should "prefill the Stripe checkout page with the purchaser's email address" do
skip "Stripe API keys not configured" unless UserUpgrade.enabled?
skip "Stripe API keys not configured" unless PaymentTransaction::Stripe.enabled?
@user = create(:user, email_address: build(:email_address))
@user_upgrade = create(:gift_gold_upgrade, purchaser: @user)
@@ -64,48 +64,48 @@ class UserUpgradeTest < ActiveSupport::TestCase
@user_upgrade = create(:self_gold_upgrade)
@checkout = @user_upgrade.create_checkout!(country: "US")
assert_equal(UserUpgrade.gold_price, @user_upgrade.payment_intent.amount)
assert_equal("usd", @user_upgrade.payment_intent.currency)
assert_equal(UserUpgrade.gold_price, @user_upgrade.transaction.amount)
assert_equal("usd", @user_upgrade.transaction.currency)
end
should "choose the right price in USD for a platinum upgrade" do
@user_upgrade = create(:self_platinum_upgrade)
@checkout = @user_upgrade.create_checkout!(country: "US")
assert_equal(UserUpgrade.platinum_price, @user_upgrade.payment_intent.amount)
assert_equal("usd", @user_upgrade.payment_intent.currency)
assert_equal(UserUpgrade.platinum_price, @user_upgrade.transaction.amount)
assert_equal("usd", @user_upgrade.transaction.currency)
end
should "choose the right price in USD for a gold to platinum upgrade" do
@user_upgrade = create(:self_gold_to_platinum_upgrade)
@checkout = @user_upgrade.create_checkout!(country: "US")
assert_equal(UserUpgrade.gold_to_platinum_price, @user_upgrade.payment_intent.amount)
assert_equal("usd", @user_upgrade.payment_intent.currency)
assert_equal(UserUpgrade.gold_to_platinum_price, @user_upgrade.transaction.amount)
assert_equal("usd", @user_upgrade.transaction.currency)
end
should "choose the right price in EUR for a gold upgrade" do
@user_upgrade = create(:self_gold_upgrade)
@checkout = @user_upgrade.create_checkout!(country: "DE")
assert_equal(0.8 * UserUpgrade.gold_price, @user_upgrade.payment_intent.amount)
assert_equal("eur", @user_upgrade.payment_intent.currency)
assert_equal(0.8 * UserUpgrade.gold_price, @user_upgrade.transaction.amount)
assert_equal("eur", @user_upgrade.transaction.currency)
end
should "choose the right price in EUR for a platinum upgrade" do
@user_upgrade = create(:self_platinum_upgrade)
@checkout = @user_upgrade.create_checkout!(country: "DE")
assert_equal(0.8 * UserUpgrade.platinum_price, @user_upgrade.payment_intent.amount)
assert_equal("eur", @user_upgrade.payment_intent.currency)
assert_equal(0.8 * UserUpgrade.platinum_price, @user_upgrade.transaction.amount)
assert_equal("eur", @user_upgrade.transaction.currency)
end
should "choose the right price in EUR for a gold to platinum upgrade" do
@user_upgrade = create(:self_gold_to_platinum_upgrade)
@checkout = @user_upgrade.create_checkout!(country: "DE")
assert_equal(0.8 * UserUpgrade.gold_to_platinum_price, @user_upgrade.payment_intent.amount)
assert_equal("eur", @user_upgrade.payment_intent.currency)
assert_equal(0.8 * UserUpgrade.gold_to_platinum_price, @user_upgrade.transaction.amount)
assert_equal("eur", @user_upgrade.transaction.currency)
end
end
@@ -119,49 +119,49 @@ class UserUpgradeTest < ActiveSupport::TestCase
@checkout = @user_upgrade.create_checkout!(country: "US")
assert_equal(["card"], @checkout.payment_method_types)
assert_equal("usd", @user_upgrade.payment_intent.currency)
assert_equal("usd", @user_upgrade.transaction.currency)
end
should "choose the right payment methods for AT" do
@checkout = @user_upgrade.create_checkout!(country: "AT")
assert_equal(["card", "eps"], @checkout.payment_method_types)
assert_equal("eur", @user_upgrade.payment_intent.currency)
assert_equal("eur", @user_upgrade.transaction.currency)
end
should "choose the right payment methods for BE" do
@checkout = @user_upgrade.create_checkout!(country: "BE")
assert_equal(["card", "bancontact"], @checkout.payment_method_types)
assert_equal("eur", @user_upgrade.payment_intent.currency)
assert_equal("eur", @user_upgrade.transaction.currency)
end
should "choose the right payment methods for DE" do
@checkout = @user_upgrade.create_checkout!(country: "DE")
assert_equal(["card", "giropay"], @checkout.payment_method_types)
assert_equal("eur", @user_upgrade.payment_intent.currency)
assert_equal("eur", @user_upgrade.transaction.currency)
end
should "choose the right payment methods for NL" do
@checkout = @user_upgrade.create_checkout!(country: "NL")
assert_equal(["card", "ideal"], @checkout.payment_method_types)
assert_equal("eur", @user_upgrade.payment_intent.currency)
assert_equal("eur", @user_upgrade.transaction.currency)
end
should "choose the right payment methods for PL" do
@checkout = @user_upgrade.create_checkout!(country: "PL")
assert_equal(["card", "p24"], @checkout.payment_method_types)
assert_equal("eur", @user_upgrade.payment_intent.currency)
assert_equal("eur", @user_upgrade.transaction.currency)
end
should "choose the right payment methods for an unsupported country" do
@checkout = @user_upgrade.create_checkout!(country: "MX")
assert_equal(["card"], @checkout.payment_method_types)
assert_equal("usd", @user_upgrade.payment_intent.currency)
assert_equal("usd", @user_upgrade.transaction.currency)
end
end
end