Skip to content

Handle payment_intent.succeeded event#222

Merged
elia merged 1 commit into
masterfrom
waiting-for-dev/handle_payment_itent_succeeded_event
Mar 17, 2023
Merged

Handle payment_intent.succeeded event#222
elia merged 1 commit into
masterfrom
waiting-for-dev/handle_payment_itent_succeeded_event

Conversation

@waiting-for-dev

Copy link
Copy Markdown
Contributor

Summary

A payment_intent.successful event is published when capturing a payment intent from the Stripe dashboard. At that point, we need to update the associated Solidus payment to be marked as completed.

However, the webhook could also be received after capturing the payment from the Solidus admin interface, as it updates through Stripe's API. Therefore, we need to do nothing if the payment is already completed.

The unit tests on the subscriber cover the handler's behavior, while at the integration layer, we're making sure that it's actually reached when the "payment_intent.succeeded" event is published. Besides, this PR has been manually tested for different checkout flows.

Closes #179

Checklist

Check out our PR guidelines for more details.

The following are mandatory for all PRs:

The following are not always needed:

  • 📖 I have updated the README to account for my changes.
  • 📑 I have documented new code with YARD.
  • 🛣️ I have opened a PR to update the guides.
  • ✅ I have added automated tests to cover my changes.
  • 📸 I have attached screenshots to demo visual changes.

@rainerdema rainerdema left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks great! Just a small consideration 👀

def complete_payment(event)
payment_intent_id = event.data.object.id
payment = Spree::Payment.find_by!(response_code: payment_intent_id)
payment.complete! unless payment.completed?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

After the event has been processed, how about saving a SolidusStripe::LogEntries.payment_log related to the event on the payment?
By doing so, it would enable the admin side to display a timeline of events related to the payment, allowing for a clearer understanding of why, in this case, the payment is marked as completed 🤔 WDYT?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Makes total sense. I just added that. Thanks for your suggestion 👍

@kennyadsl kennyadsl left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice and simple. I left a question about a method name that I don't fully understand, but it's most likely me.

@stripe_object ||= Stripe::Event.construct_from(data)
end

def solidus_stripe_object

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you please help me understand why this method is called solidus_stripe_object and returns a Webhook Event?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The EventWithContext class can return a Stripe event in different representations:

  • #json: A JSON string representation
  • #signature_header: How it looks signed in the request header
  • #stripe_object: As a Stripe::Event object.
  • #solidus_stripe_object: As a SolidusStripe::Webhook::Event object.

I know it's a bit cryptic, but I can't find better candidates. We can't call the #stripe_object method #stripe_event, because all those methods return representations of a Stripe event. Once we have that method, the most logical candidate for the new addition is #solidus_stripe_object.

Happy to change it if we find a better solution!!

@waiting-for-dev waiting-for-dev force-pushed the waiting-for-dev/handle_payment_itent_succeeded_event branch from e49258b to c897dd6 Compare March 17, 2023 04:35
A `payment_intent.successful` event is published [1] when capturing a
payment intent from the Stripe dashboard. At that point, we need to
update the associated Solidus payment to be marked as completed.

However, the webhook could also be received after capturing the payment
from the Solidus admin interface, as it updates through Stripe's API.
Therefore, we need to do nothing if the payment is already completed.

The unit tests on the subscriber cover the handler's behavior, while at
the integration layer, we're making sure that it's actually reached when
the "payment_intent.succeeded" event is published. Besides, this PR has
been manually tested for different checkout flows.

Closes #179

[1] - https://stripe.com/docs/payments/payment-intents/verifying-status#webhooks
@waiting-for-dev waiting-for-dev force-pushed the waiting-for-dev/handle_payment_itent_succeeded_event branch from c897dd6 to 2a50f80 Compare March 17, 2023 05:08

@rainerdema rainerdema left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚢

@elia elia merged commit 61684eb into master Mar 17, 2023
@elia elia deleted the waiting-for-dev/handle_payment_itent_succeeded_event branch March 17, 2023 17:10
waiting-for-dev added a commit that referenced this pull request Mar 21, 2023
…t creation

On #222, we're handling the `payment_intent.succeeded` webhook by
fetching the associated payment via the `Spree::Payment#response_code`
field. However, the response code wasn't filled until after the
authorization was completed on Stripe. Once we implement auto-capture
(see #178), that could be an issue, as we could receive the webhook
before the column update.

We're now filling `response_code` just after the payment intent
creation, which always happens before confirmation on Stripe (see #231).

Closes #238
waiting-for-dev added a commit that referenced this pull request Mar 21, 2023
…t creation

On #222, we're handling the `payment_intent.succeeded` webhook by
fetching the associated payment via the `Spree::Payment#response_code`
field. However, the response code wasn't filled until after the
authorization was completed on Stripe. Once we implement auto-capture
(see #178), that could be an issue, as we could receive the webhook
before the column update.

We're now filling `response_code` just after the payment intent
creation, which always happens before confirmation on Stripe (see #231).

Closes #238
waiting-for-dev added a commit that referenced this pull request Mar 22, 2023
…t creation

On #222, we're handling the `payment_intent.succeeded` webhook by
fetching the associated payment via the `Spree::Payment#response_code`
field. However, the response code wasn't filled until after the
authorization was completed on Stripe. Once we implement auto-capture
(see #178), that could be an issue, as we could receive the webhook
before the column update.

We're now filling `response_code` just after the payment intent
creation, which always happens before confirmation on Stripe (see #231).

Closes #238
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.

Handle payment_intent.succeeded webhook event

4 participants