Skip to content

Commit 3e3dfd4

Browse files
fupelaquclaude
andcommitted
fix: use explicit cardId in RegisterRecurringPayment instead of first active card (#24)
When a user with multiple cards subscribes, the system was always picking the first active card instead of the one selected during checkout. Added cardId parameter to the command, proto event, and command handler with backward-compatible fallback to first active card when not specified.Closes Issue #24 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 4212ec9 commit 3e3dfd4

6 files changed

Lines changed: 28 additions & 18 deletions

File tree

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ ThisBuild / organization := "app.softnetwork"
1818

1919
name := "payment"
2020

21-
ThisBuild / version := "0.9.6"
21+
ThisBuild / version := "0.9.7"
2222

2323
ThisBuild / scalaVersion := scala212
2424

common/src/main/protobuf/message/payment/payment.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ message RegisterRecurringPaymentCommandEvent {
290290
optional int32 nextDebitedAmount = 10;
291291
optional int32 nextFeesAmount = 11;
292292
optional string clientId = 12;
293+
optional string cardId = 13;
293294
}
294295

295296
message RecurringPaymentRegisteredEvent {

common/src/main/scala/app/softnetwork/payment/message/PaymentMessages.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,9 @@ object PaymentMessages {
503503
* - statement descriptor
504504
* @param externalReference
505505
* - optional external reference
506+
* @param cardId
507+
* - optional card id to use for the recurring payment (if not provided, the first active card
508+
* will be used)
506509
* @param clientId
507510
* - optional client id
508511
*/
@@ -521,6 +524,7 @@ object PaymentMessages {
521524
statementDescriptor: Option[String] = None,
522525
externalReference: Option[String] = None,
523526
metadata: Map[String, String] = Map.empty,
527+
cardId: Option[String] = None,
524528
clientId: Option[String] = None
525529
) extends PaymentCommandWithKey
526530
with RecurringPaymentCommand {

core/src/main/scala/app/softnetwork/payment/persistence/query/PaymentCommandProcessorStream.scala

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -181,18 +181,19 @@ trait PaymentCommandProcessorStream extends EventProcessorStream[PaymentEventWit
181181
case evt: RegisterRecurringPaymentCommandEvent =>
182182
import evt._
183183
val command = RegisterRecurringPayment(
184-
debitedAccount,
185-
firstDebitedAmount,
186-
firstFeesAmount,
187-
currency,
188-
`type`,
189-
startDate,
190-
endDate,
191-
frequency,
192-
fixedNextAmount,
193-
nextDebitedAmount,
194-
nextFeesAmount,
195-
clientId
184+
debitedAccount = debitedAccount,
185+
firstDebitedAmount = firstDebitedAmount,
186+
firstFeesAmount = firstFeesAmount,
187+
currency = currency,
188+
`type` = `type`,
189+
startDate = startDate,
190+
endDate = endDate,
191+
frequency = frequency,
192+
fixedNextAmount = fixedNextAmount,
193+
nextDebitedAmount = nextDebitedAmount,
194+
nextFeesAmount = nextFeesAmount,
195+
cardId = cardId,
196+
clientId = clientId
196197
)
197198
!?(command) map {
198199
case _: RecurringPaymentRegistered =>

core/src/main/scala/app/softnetwork/payment/persistence/typed/RecurringPaymentCommandHandler.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,13 @@ trait RecurringPaymentCommandHandler
101101
case Some(userId) =>
102102
paymentAccount.walletId match {
103103
case Some(walletId) =>
104-
paymentAccount.cards
105-
.filterNot(_.expired)
106-
.find(_.getActive)
107-
.map(_.id) match {
104+
cmd.cardId
105+
.orElse(
106+
paymentAccount.cards
107+
.filterNot(_.expired)
108+
.find(_.getActive)
109+
.map(_.id)
110+
) match {
108111
case Some(cardId) =>
109112
val createdDate = now()
110113
var recurringPayment =

testkit/src/test/scala/app/softnetwork/payment/service/StripePaymentServiceSpec.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,8 @@ trait StripePaymentServiceSpec[SD <: SessionData with SessionDataDecorator[SD]]
10421042
endDate = Some(LocalDate.now().plusMonths(1)),
10431043
fixedNextAmount = Some(true),
10441044
nextDebitedAmount = Some(4990),
1045-
nextFeesAmount = Some(0)
1045+
nextFeesAmount = Some(0),
1046+
cardId = Some(cardId)
10461047
)
10471048
)
10481049
) ~> routes ~> check {

0 commit comments

Comments
 (0)