Skip to content

RegisterRecurringPayment ignores checkout card when multiple cards are active #24

Description

@fupelaqu

Bug Description

When a user has multiple active payment cards and subscribes to a new recurring plan using a specific card, the subscription is incorrectly associated with the first active card instead of the card used in the checkout.

Steps to Reproduce

  1. Subscribe to a monthly pro license using card ending in 4242
  2. Subscribe to an annual pro license using a different card ending in 3184 (3DS required)
  3. View the billing page

Expected: Annual subscription shows card 3184 (the card used during checkout)
Actual: Annual subscription shows card 4242 (the first active card)

Root Cause

In RecurringPaymentCommandHandler.scala (lines 104-107), the card selection uses:

paymentAccount.cards
  .filterNot(_.expired)
  .find(_.getActive)  // Returns FIRST active card, not the intended one
  .map(_.id)

The RegisterRecurringPayment command has no cardId field, so there is no way to communicate which card was used in the checkout flow. By contrast, UpdateRecurringCardPaymentRegistration correctly accepts an optional cardId.

Proposed Fix

  1. Add cardId: Option[String] = None to RegisterRecurringPayment in PaymentMessages.scala
  2. In RecurringPaymentCommandHandler, use cmd.cardId.orElse(paymentAccount.cards.filterNot(_.expired).find(_.getActive).map(_.id)) for backward compatibility
  3. Pass the selected card ID from the portal checkout flow when calling the register endpoint

Files Involved

  • common/src/main/scala/app/softnetwork/payment/message/PaymentMessages.scala — missing cardId field
  • core/src/main/scala/app/softnetwork/payment/persistence/typed/RecurringPaymentCommandHandler.scala — buggy card selection (line 104-107)
  • core/src/main/scala/app/softnetwork/payment/service/RecurringPaymentEndpoints.scala — endpoint doesn't pass card info
  • stripe/src/main/scala/app/softnetwork/payment/spi/StripeRecurringPaymentApi.scala — correctly uses card ID when passed

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions