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

Fixed Updating customer billing address now correctly reflected to stripe #3696

Open
wants to merge 16 commits into
base: master
Choose a base branch
from

Conversation

nidhi-soni1104
Copy link
Contributor

@nidhi-soni1104 nidhi-soni1104 commented Feb 20, 2024

What this PR does / why we need it:

Changing customer billing address, in the developer portal, is updated to Stripe only when credit card details are changed. Just editing and saving billing address details creates problems, when customer details are not consistent between 3scale and Stripe. This can be forcefully fixed, when the customer updates their credit card information as well.

Expected behavior:

Editing just billing address details should update customer details on Stripe.

Which issue(s) this PR fixes
https://issues.redhat.com/browse/THREESCALE-9532

Verification steps
Mentioned in jira with snapshots

@nidhi-soni1104 nidhi-soni1104 self-assigned this Feb 20, 2024
@nidhi-soni1104 nidhi-soni1104 marked this pull request as draft February 20, 2024 08:21
@nidhi-soni1104 nidhi-soni1104 marked this pull request as ready for review March 4, 2024 13:54
@nidhi-soni1104 nidhi-soni1104 force-pushed the THREESCALE-9532-fix-stripe-billing-adress-update branch from 4173d32 to be59a8d Compare March 4, 2024 13:55
@nidhi-soni1104 nidhi-soni1104 force-pushed the THREESCALE-9532-fix-stripe-billing-adress-update branch from a8ee671 to 5024303 Compare March 11, 2024 08:45
rescue Stripe::StripeError => stripe_error
handle_stripe_error(stripe_error)
ensure
reset_stripe_api_key
Copy link
Contributor

Choose a reason for hiding this comment

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

@nidhi-soni1104 Can you explain, why do we need to set and unset the Stripe key this way?... Can't we just keep passing it to #retrieve as a second argument?

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 did this because when I tried updating on stripe passing Stripe key as second argument, it didn't get updated and then I tried it n number of times with other different ways but only this method worked for me .

Stripe.api_key = api_key # Set actual Stripe secret key
latest_payment_method_id = latest_payment_method_id_for_customer
return true unless latest_payment_method_id.present?
payment_method = Stripe::PaymentMethod.retrieve(payment_method_id)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm getting an error here when trying to update the address:
image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ummmm I have not received this error but let me try to reproduce it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mayorova Yes due to code refactor id name was passed wrong

I have fixed it and now it works well

image
Uploading image.png…

@@ -41,6 +41,19 @@ def notify_exception(e, query_string = nil)
Rails.logger.error(msg)
end

def update_payment_detail(card, payment_method_id, payment_method)
Copy link
Contributor

@mayorova mayorova Apr 10, 2024

Choose a reason for hiding this comment

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

This method, as well as handle_stripe_error cannot be here, because they are Stripe-specific, and also payment_detail is only defined in StripeCrypt, so this code needs to be moved there.

payment_detail.credit_card_auth_code = payment_method.customer
payment_detail.payment_method_id = payment_method_id
payment_detail.save
update_payment_detail(card, payment_method_id, payment_method)
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems that card belongs to payment_method, so we don't need to path both to the method. You can pass just (payment_method, payment_method_id), and move the card = payment_method.card line within the method.

payment_method.save
end

def retrieve_customer(customer_id)
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the purpose of this refactor?... 🤔

I'd probably keep it as it is, the method is not too long, and splitting it I think makes it less readable.

@@ -28,7 +28,7 @@ def edit
def update
current_account.updating_payment_detail = true
if current_account.update account_params
redirect_to payment_details_path, notice: 'Your billing address was successfully stored'
update_billing_address_on_stripe(account_params)
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 is a bit concerning, because this controller is generic, and not Stripe-specific.
I've been looking in to this, and it seems that we currently support just Stripe and Braintree, and Braintree doesn't use this path, so it's kind of fine (in the sense that it doesn't break the Braintree flow). Also, it seems that we can't move this to the Stripe controller, because we don't want to break the existing portals.

But I think we do need to at least check here whether the current account's payment gateway is actually stripe, before trying to update anything.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hm... probably we can actually change this (e.g. by moving the method to the Stripe Controller) without breaking the portals, because this path is not in the template, but in the Liquid drop:

admin_account_payment_details_path

But we need to think about whether that's the right thing to do.

@@ -36,21 +32,41 @@ def customer
@customer ||= find_or_create_customer
end

def update_billing_address(billing_address)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's quite confusing to have update_billing_address, update_billing_details and update_and_save_billing_details methods, as you need to jump between them to understand what is done there.

At least the last two need to be merged, IMO.

@@ -28,7 +28,7 @@ def edit
def update
current_account.updating_payment_detail = true
if current_account.update account_params
redirect_to payment_details_path, notice: 'Your billing address was successfully stored'
update_billing_address_on_stripe(account_params)
Copy link
Contributor

@mayorova mayorova Apr 10, 2024

Choose a reason for hiding this comment

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

Also, this is a bit hard to follow - I'd avoid having a redirect, and a duplicated error-rendering functionality in a method.
Instead, I would do something like this:

if update_address_on_gateway && current_account.update account_params
  redirect_to payment_details_path, notice: 'Your billing address was successfully stored'
else
  flash[:notice] ...
end

And then (in pseudocode):

def update_address_on_gateway
  return true if <payment gateway is not Stripe>

  <the code updating the address in Stripe, returning true or false>
end

But probably still better to move this whole method to the Stripe controller.

Comment on lines +92 to +97
latest_payment_method = Stripe::PaymentMethod.list(
customer: customer.id,
type: 'card',
limit: 1
).data.first&.id
end
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this is a reliable method to get the right payment mehtod 🤔
Are we sure about the order of the list? Maybe the first one added will be returned here, and not the one that was added last?

What we actually care about is the payment method which is identified by payment_method_id that we store in our database. So, I think we need to retrieve that one (I guess it would be something like Stripe::PaymentMethod.retrieve(current_account.payment_detail.payment_method_id, api_key)), and update it instead.

payment_method = Stripe::PaymentMethod.retrieve(latest_payment_method_id)
update_and_save_billing_details(payment_method, billing_address)
rescue Stripe::StripeError => stripe_error
handle_stripe_error(stripe_error)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't you just report_error("Failed to update billing address on Stripe: #{stripe_error.message}") here? I think the handle_stripe_error is not needed at all.

Copy link

This PR is stale because it has not received activity for more than 30 days. Remove stale label or comment or this will be closed in 15 days.

@github-actions github-actions bot added the Stale label May 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants