Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

Commit

Permalink
fix: Capture-context modification for existing Payment Intents in com…
Browse files Browse the repository at this point in the history
…firmable status
  • Loading branch information
julianajlk committed Apr 18, 2024
1 parent 5482fe2 commit ba2f731
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
11 changes: 10 additions & 1 deletion ecommerce/extensions/payment/processors/stripe.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,16 @@ def get_capture_context(self, request):
if payment_intent_id:
stripe_response = stripe.PaymentIntent.retrieve(id=payment_intent_id)
status = stripe_response['status']
if status != 'requires_payment_method' or status != 'requires_confirmation':
logger.info(
'Stripe capture-context called for basket [%d] and order number [%s] with '
'existing Payment Intent [%s] with status [%s]',
basket.id,
basket.order_number,
payment_intent_id,
status,
)
confirmable_statuses = ['requires_payment_method', 'requires_confirmation']
if status not in confirmable_statuses:
# Payment Intent is in a non-confirmable status, must create a new one
stripe_response = self.cancel_and_create_new_payment_intent_for_basket(basket, payment_intent_id)
# If a Payment Intent exists in a confirmable status, it will skip the below else statement,
Expand Down
32 changes: 32 additions & 0 deletions ecommerce/extensions/payment/tests/views/test_stripe.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,38 @@ def test_capture_context_large_characters_basket(self):
# The metadata must be less than 500 characters
assert len(mock_create.call_args.kwargs['metadata']['courses']) < 500

@file_data('fixtures/test_stripe_test_payment_flow.json')
def test_capture_context_confirmable_status(
self,
confirm_resp, # pylint: disable=unused-argument
confirm_resp_in_progress, # pylint: disable=unused-argument
create_resp,
modify_resp, # pylint: disable=unused-argument
cancel_resp,
refund_resp, # pylint: disable=unused-argument
retrieve_addr_resp,
retrieve_resp_in_progress): # pylint: disable=unused-argument
"""
Verify that hitting capture-context with a Payment Intent that already exists and it's in a status that
can be confirmed, that a new Payment Intent is not created for this basket.
"""
basket = self.create_basket(product_class=SEAT_PRODUCT_CLASS_NAME)
payment_intent_id = retrieve_addr_resp['id']
basket_add_payment_intent_id_attribute(basket, payment_intent_id)

with mock.patch('stripe.PaymentIntent.retrieve') as mock_retrieve:
mock_retrieve.return_value = retrieve_addr_resp
# If Payment Intent already exists for this basket, and it's in a usable status that
# can later be confirmed, make sure we do not cancel and create a new Payment Intent.
with mock.patch('stripe.PaymentIntent.cancel') as mock_cancel:
self.client.get(self.capture_context_url)
mock_cancel.assert_not_called()
payment_intent_id = BasketAttribute.objects.get(
basket=basket,
attribute_type__name=PAYMENT_INTENT_ID_ATTRIBUTE
).value_text
assert payment_intent_id == mock_retrieve.return_value['id']

@file_data('fixtures/test_stripe_test_payment_flow.json')
def test_capture_context_in_progress_payment(
self,
Expand Down

0 comments on commit ba2f731

Please sign in to comment.