isExpired aborts payments that could pass on Stripe

Created on 29 April 2024, 9 months ago
Updated 2 July 2024, 7 months ago

Problem/Motivation

According to Stripe, It is possible for a card to be deducted even when it's expired.

If a card was saved to Stripe before it expired, it sometimes can continue to be charged after its expiration date has passed. The decision to allow the charge to go through is entirely up to the issuing bank...

Calling assertPaymentMethod in createPayment() checks for the card's expiry and prevents the payment attempt from going through. I think in this case the expiry check should not be done on drupal and rather leave it to the payment gateway's system.

Proposed resolution

There's an argument to be made to adjust assertPaymentMethod's code in commerce core but if this is an exclusive rule for stripe then assertPaymentMethod can be replaced with a !empty() check to skip the isExpired check.

πŸ› Bug report
Status

Fixed

Version

1.0

Component

Code

Created by

πŸ‡―πŸ‡΄Jordan mhawwari

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @mhawwari
  • πŸ‡―πŸ‡΄Jordan mhawwari

    mhawwari β†’ changed the visibility of the branch 3444153-isexpired-aborts-payments to hidden.

  • πŸ‡―πŸ‡΄Jordan mhawwari

    mhawwari β†’ changed the visibility of the branch 3444153-isexpired-aborts-payments to active.

  • Merge request !98Issue #3444153: skip expired card checks β†’ (Merged) created by mhawwari
  • Pipeline finished with Success
    9 months ago
    Total: 846s
    #159854
  • Issue was unassigned.
  • Status changed to Needs review 9 months ago
  • πŸ‡¬πŸ‡§United Kingdom jonathanshaw Stroud, UK

    This closely relates to #3171270: Support 'smarter saved cards' β†’ with same proposed solution.

  • First commit to issue fork.
  • Assigned to TomTech
  • πŸ‡ΊπŸ‡ΈUnited States TomTech

    This is reasonable.

    In the past, sites were expected to not submit expired cards for payment, as it appeared as suspicious activity. Fraud prevention measures have evolved.

    Even if the expired date is "valid", the card could have been reported lost/stolen and the card would still not work anyway.

    Thanks for the MR!

  • Status changed to Fixed 8 months ago
  • πŸ‡ΊπŸ‡ΈUnited States TomTech
  • Status changed to Needs work 8 months ago
  • πŸ‡¬πŸ‡§United Kingdom jonathanshaw Stroud, UK

    The fix may be wrong.

    PaymentGatewayBase has this:

      protected function assertPaymentMethod(PaymentMethodInterface $payment_method = NULL) {
        if (empty($payment_method)) {
          throw new \InvalidArgumentException('The provided payment has no payment method referenced.');
        }
        if ($payment_method->isExpired()) {
          throw HardDeclineException::createForPayment($payment_method, 'The provided payment method has expired');
        }
      }
    

    Wouldn't the correct solution be to keep the calls to assertPaymenMethod() but to override and simplify the method:

      /**
       * {@inheritdoc}
       */
      protected function assertPaymentMethod(PaymentMethodInterface $payment_method = NULL) {
        if (empty($payment_method)) {
          throw new \InvalidArgumentException('The provided payment has no payment method referenced.');
        }
      }
    
  • Status changed to Fixed 8 months ago
  • πŸ‡ΊπŸ‡ΈUnited States TomTech

    Hi @jonathanshaw,

    That would seem so, except the preceding line in both classes was already doing:

        assert($payment_method instanceof PaymentMethodInterface);
        $this->assertPaymentMethod($payment_method);
    

    Because of the assert, payment_method would already be checked for existence, so that would be a redundant check that would never be true.

    One could discuss whether assert() should be used at all, but it has been there for ~5 years, and would be more appropriate for another issue to discuss assert() usage.

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024