diff --git a/app/controllers/pay/webhooks/stripe_controller.rb b/app/controllers/pay/webhooks/stripe_controller.rb index bc718293..376b27ba 100644 --- a/app/controllers/pay/webhooks/stripe_controller.rb +++ b/app/controllers/pay/webhooks/stripe_controller.rb @@ -6,7 +6,8 @@ class StripeController < Pay::ApplicationController end def create - queue_event(verified_event) + event = verified_event + queue_event(event) if event.livemode || Pay::Stripe.webhook_receive_test_events head :ok rescue ::Stripe::SignatureVerificationError => e log_error(e) diff --git a/docs/2_configuration.md b/docs/2_configuration.md index 67ccca7e..fa0d79ab 100644 --- a/docs/2_configuration.md +++ b/docs/2_configuration.md @@ -21,6 +21,7 @@ stripe: private_key: xxxx public_key: yyyy signing_secret: + webhook_receive_test_events: true - aaaa - bbbb braintree: @@ -56,6 +57,7 @@ Pay will also check environment variables for API keys: * `STRIPE_PUBLIC_KEY` * `STRIPE_PRIVATE_KEY` * `STRIPE_SIGNING_SECRET` +* `STRIPE_WEBHOOK_RECEIVE_TEST_EVENTS` * `BRAINTREE_MERCHANT_ID` * `BRAINTREE_PUBLIC_KEY` * `BRAINTREE_PRIVATE_KEY` @@ -71,6 +73,9 @@ Pay will also check environment variables for API keys: * `PADDLE_CLASSIC_PUBLIC_KEY_BASE64` * `PADDLE_CLASSIC_ENVIRONMENT` +#### STRIPE_WEBHOOK_RECEIVE_TEST_EVENTS (Default to TRUE) +As per the guidance from https://support.stripe.com/questions/connect-account-webhook-configurations: "When a connected account is linked solely in live mode to your platform, both live and test events are sent to your live Connect Webhook Endpoint." Therefore, you can set this to false if you wish to receive only live events in Production. + ## Generators If you want to modify the Stripe SCA template or any other views, you can copy over the view files using: diff --git a/lib/pay/stripe.rb b/lib/pay/stripe.rb index 0593ee0b..f551a3f6 100644 --- a/lib/pay/stripe.rb +++ b/lib/pay/stripe.rb @@ -66,6 +66,11 @@ def self.signing_secret find_value_by_name(:stripe, :signing_secret) end + def self.webhook_receive_test_events + value = find_value_by_name(:stripe, :webhook_receive_test_events) + value.blank? ? true : ActiveModel::Type::Boolean.new.cast(value) + end + def self.configure_webhooks Pay::Webhooks.configure do |events| # Listen to the charge event to make sure we get non-subscription diff --git a/test/controllers/pay/webhooks/stripe_controller_test.rb b/test/controllers/pay/webhooks/stripe_controller_test.rb index 296fc039..e6032654 100644 --- a/test/controllers/pay/webhooks/stripe_controller_test.rb +++ b/test/controllers/pay/webhooks/stripe_controller_test.rb @@ -14,23 +14,9 @@ class StripeWebhooksControllerTest < ActionDispatch::IntegrationTest end test "should parse a stripe webhook" do - params = { - "id" => "evt_3JMPQbQK2ZHS99Rk0zZhIl7y", - "object" => "event", - "api_version" => "2020-08-27", - "created" => 1628480731, - "data" => fake_event("stripe/charge.succeeded"), - "livemode" => false, - "pending_webhooks" => 3, - "request" => { - "id" => nil, - "idempotency_key" => "in_1JMOTyQK2ZHS99Rk3k06zB02-initial_attempt-0dee959767cdedcc1" - }, - "type" => "charge.succeeded" - } + params = stripe_params(livemode: true) + stripe_event = create_stripe_event(params) - stripe_event = ::Stripe::Event.construct_from(params) - Pay::Webhooks::StripeController.any_instance.expects(:verified_event).returns(stripe_event) ::Stripe::Charge.expects(:retrieve).returns(stripe_event.data.object) pay_customer = pay_customers(:stripe) @@ -47,5 +33,62 @@ class StripeWebhooksControllerTest < ActionDispatch::IntegrationTest perform_enqueued_jobs end end + + test "should not enqueue a job for a test event if webhook_receive_test_events is false" do + with_modified_env("STRIPE_WEBHOOK_RECEIVE_TEST_EVENTS" => "false") do + params = stripe_params(livemode: false) + create_stripe_event(params) + + assert_no_difference "Pay::Webhook.count" do + post webhooks_stripe_path, params: params + assert_response :success + end + end + end + + test "should enqueue a job for a test event if webhook_receive_test_events is true" do + with_modified_env("STRIPE_WEBHOOK_RECEIVE_TEST_EVENTS" => "true") do + params = stripe_params(livemode: false) + create_stripe_event(params) + + assert_difference "Pay::Webhook.count" do + post webhooks_stripe_path, params: params + assert_response :success + end + end + end + + private + + def stripe_params(livemode:) + { + "id" => "evt_3JMPQbQK2ZHS99Rk0zZhIl7y", + "object" => "event", + "api_version" => "2020-08-27", + "created" => 1628480731, + "data" => fake_event("stripe/charge.succeeded"), + "livemode" => livemode, + "pending_webhooks" => 3, + "request" => { + "id" => nil, + "idempotency_key" => "in_1JMOTyQK2ZHS99Rk3k06zB02-initial_attempt-0dee959767cdedcc1" + }, + "type" => "charge.succeeded" + } + end + + def create_stripe_event(params) + stripe_event = ::Stripe::Event.construct_from(params) + Pay::Webhooks::StripeController.any_instance.expects(:verified_event).returns(stripe_event) + stripe_event + end + + def with_modified_env(options, &block) + old_env = ENV.to_hash + ENV.update(options) + yield + ensure + ENV.update(old_env) + end end end diff --git a/test/pay/stripe_test.rb b/test/pay/stripe_test.rb index 50f6a91b..0be72ec2 100644 --- a/test/pay/stripe_test.rb +++ b/test/pay/stripe_test.rb @@ -6,12 +6,25 @@ class Pay::Stripe::Test < ActiveSupport::TestCase ENV.update( "STRIPE_PUBLIC_KEY" => "public", "STRIPE_PRIVATE_KEY" => "private", - "STRIPE_SIGNING_SECRET" => "secret" + "STRIPE_SIGNING_SECRET" => "secret", + "STRIPE_WEBHOOK_RECEIVE_TEST_EVENTS" => "false" ) assert_equal "public", Pay::Stripe.public_key assert_equal "private", Pay::Stripe.private_key assert_equal "secret", Pay::Stripe.signing_secret + assert_equal false, Pay::Stripe.webhook_receive_test_events + ensure + ENV.update(old_env) + end + + test "webhook_receive_test_events default to true" do + old_env = ENV.to_hash + ENV.update( + "STRIPE_WEBHOOK_RECEIVE_TEST_EVENTS" => nil + ) + + assert_equal true, Pay::Stripe.webhook_receive_test_events ensure ENV.update(old_env) end