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.
153 lines
5.8 KiB
Ruby
153 lines
5.8 KiB
Ruby
require 'test_helper'
|
|
|
|
class WebhooksControllerTest < ActionDispatch::IntegrationTest
|
|
setup do
|
|
StripeMock.start
|
|
end
|
|
|
|
teardown do
|
|
StripeMock.stop
|
|
end
|
|
|
|
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 }
|
|
|
|
post receive_webhooks_path(source: "stripe"), headers: headers, params: event, as: :json
|
|
end
|
|
|
|
# https://github.com/stripe-ruby-mock/stripe-ruby-mock/issues/467#issuecomment-634674913
|
|
# https://stripe.com/docs/webhooks/signatures
|
|
def generate_stripe_signature(event)
|
|
time = Time.now
|
|
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
|
|
|
|
context "The webhooks controller" do
|
|
context "receive action" do
|
|
context "for a request from an unrecognized source" do
|
|
should "fail" do
|
|
post receive_webhooks_path(source: "blah")
|
|
assert_response 400
|
|
end
|
|
end
|
|
|
|
context "for a Stripe webhook" do
|
|
context "with a missing signature" do
|
|
should "fail" do
|
|
event = StripeMock.mock_webhook_event("payment_intent.created")
|
|
post receive_webhooks_path(source: "stripe"), params: event, as: :json
|
|
|
|
assert_response 400
|
|
end
|
|
end
|
|
|
|
context "with an invalid signature" do
|
|
should "fail" do
|
|
event = StripeMock.mock_webhook_event("payment_intent.created")
|
|
headers = { "Stripe-Signature": "blah" }
|
|
post receive_webhooks_path(source: "stripe"), headers: headers, params: event, as: :json
|
|
|
|
assert_response 400
|
|
end
|
|
end
|
|
|
|
context "for a payment_intent.created event" do
|
|
should "work" do
|
|
post_stripe_webhook("payment_intent.created")
|
|
|
|
assert_response 200
|
|
end
|
|
end
|
|
|
|
context "for a checkout.session.completed event" do
|
|
context "for completed event with an unpaid payment status" do
|
|
should "not upgrade the user" do
|
|
@user_upgrade = create(:self_gold_upgrade)
|
|
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)
|
|
assert_equal(User::Levels::MEMBER, @user_upgrade.recipient.reload.level)
|
|
end
|
|
end
|
|
|
|
context "for a self upgrade" do
|
|
context "to Gold" do
|
|
should "upgrade the user" do
|
|
@user_upgrade = create(:self_gold_upgrade)
|
|
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
|
|
|
assert_response 200
|
|
assert_equal("complete", @user_upgrade.reload.status)
|
|
assert_equal(User::Levels::GOLD, @user_upgrade.recipient.reload.level)
|
|
end
|
|
end
|
|
|
|
context "to Platinum" do
|
|
should "upgrade the user" do
|
|
@user_upgrade = create(:self_platinum_upgrade)
|
|
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
|
|
|
assert_response 200
|
|
assert_equal("complete", @user_upgrade.reload.status)
|
|
assert_equal(User::Levels::PLATINUM, @user_upgrade.recipient.reload.level)
|
|
end
|
|
end
|
|
|
|
context "from Gold to Platinum" do
|
|
should "upgrade the user" do
|
|
@user_upgrade = create(:self_gold_to_platinum_upgrade)
|
|
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
|
|
|
assert_response 200
|
|
assert_equal("complete", @user_upgrade.reload.status)
|
|
assert_equal(User::Levels::PLATINUM, @user_upgrade.recipient.reload.level)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "for a gifted upgrade" do
|
|
context "to Gold" do
|
|
should "upgrade the user" do
|
|
@user_upgrade = create(:gift_gold_upgrade)
|
|
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
|
|
|
assert_response 200
|
|
assert_equal("complete", @user_upgrade.reload.status)
|
|
assert_equal(User::Levels::GOLD, @user_upgrade.recipient.reload.level)
|
|
end
|
|
end
|
|
|
|
context "to Platinum" do
|
|
should "upgrade the user" do
|
|
@user_upgrade = create(:gift_platinum_upgrade)
|
|
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
|
|
|
assert_response 200
|
|
assert_equal("complete", @user_upgrade.reload.status)
|
|
assert_equal(User::Levels::PLATINUM, @user_upgrade.recipient.reload.level)
|
|
end
|
|
end
|
|
|
|
context "from Gold to Platinum" do
|
|
should "upgrade the user" do
|
|
@user_upgrade = create(:gift_gold_to_platinum_upgrade)
|
|
post_stripe_webhook("checkout.session.completed", metadata: { user_upgrade_id: @user_upgrade.id })
|
|
|
|
assert_response 200
|
|
assert_equal("complete", @user_upgrade.reload.status)
|
|
assert_equal(User::Levels::PLATINUM, @user_upgrade.recipient.reload.level)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|