Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

THREESCALE-11383: Ignore errors on payment gateway initialization when destroying buyer #3900

Merged
merged 1 commit into from
Oct 7, 2024

Conversation

mayorova
Copy link
Contributor

What this PR does / why we need it:

If payment gateway configuration is invalid on a provider account, their buyers cannot be deleted because the unstore_credit_card! method is called as before_destroy callback.

Specifically, if the payment gateway type is :stripe, but the gateway settings stored in the database miss the login field, the payment gateway instance cannot be initialized, and the whole operation fails.

This PR catches the error, raises a more specific Account::Gateway::InvalidSettingsError error and "swallows" it the unstore_credit_card!, thus allowing for the destroy to complete successfully.

Which issue(s) this PR fixes

https://issues.redhat.com/browse/THREESCALE-11383

Verification steps

Steps to reproduce or to confirm that that issue is not reproducible in the branch:

pgs = PaymentGatewaySetting.new(gateway_type: :stripe, gateway_settings: { test: 1, private_key: "foo", merchant_id: "bar", public_key: "foobar" })

provider = FactoryBot.create(:provider_account, payment_gateway_setting: pgs)

buyer = FactoryBot.create(:buyer_account, provider_account: provider)

buyer.smart_destroy

The destroy operation should succeed and not throw errors.

Special notes for your reviewer:

@@ -18,6 +20,8 @@ def payment_gateway(**options)
return if payment_gateway_type.blank?

PaymentGateway.implementation(payment_gateway_type, **options).new(payment_gateway_options || {})
rescue ArgumentError => exception
raise InvalidSettingsError, exception.message
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My question is whether we should raise here? Or should we return something like InvalidPaymentGateway object instead? It seems pretty easy to configure an invalid gateway and handling exceptions might be less straightforward than returning an object that can have programmed the desired behavior 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I'm not sure to be honest whether it's "easy" to misconfigure it... I'm not sure in fact how it is possible 😬 (and how that "bad" configuration got there in the first place)

Looks like the current implementation returns nil if payment_gateway_type is blank. In fact, I am not sure what consequences it might have...

To me throwing an exception seems to be more logical and straightforward than returning a InvalidPaymentGateway... but it could be done also.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@akostadinov So, what do you think?

I am a bit concerned that we may throw this exception in production. But on the other hand, currently an exception would also be thrown, so the current behavior actually wouldn't change 😅 It would just give us more useful info about the error in BugSnag.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still believe that we should not throw but return an object. Still this fixes a real issue and is a net improvement in behavior so I'm approving. Thank you.

akostadinov
akostadinov previously approved these changes Oct 7, 2024
@@ -96,8 +96,12 @@ def delete_cc_details
end

def unstore_credit_card!
response = provider_payment_gateway.try!(:threescale_unstore, credit_card_auth_code)
log_gateway_response(response, "unstore [auth: #{credit_card_auth_code}]")
begin
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line can be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I trusted you and removed the line, but then I realized that this end in line :104 doesn't actually end the method, so I think we can't get rid of begin.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my bad, I overlooked that, thought you added by mistake

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although then there is a check return if payment_detail.destroyed? which idk how it is supposed to work. Maybe we should make the rescue global for the method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these are need to be executed in any case:

    self.credit_card_auth_code = nil
    self.credit_card_expires_on = nil
    self.credit_card_partial_number = nil

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't care about these other values. If things work in real life as they are now, then I'm fine with it. I was just worried that by invalid configuration payment_detail may raise. But I think your test ensures it wouldn't.

@mayorova mayorova force-pushed the ignore-gateway-init-error-on-buyer-destroy branch from 1239cfc to a6719ba Compare October 7, 2024 08:46
@mayorova mayorova merged commit 07d54df into master Oct 7, 2024
16 of 21 checks passed
@mayorova mayorova deleted the ignore-gateway-init-error-on-buyer-destroy branch October 7, 2024 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants