@@ -661,6 +661,8 @@ public async Task<SubscriptionInfo> GetSubscriptionAsync(ISubscriber subscriber)
661661 subscriptionInfo . CustomerDiscount = new SubscriptionInfo . BillingCustomerDiscount ( discount ) ;
662662 }
663663
664+ await ApplySchedulePhase2DataAsync ( subscription , subscriptionInfo ) ;
665+
664666 var ( suspensionDate , unpaidPeriodEndDate ) = await GetSuspensionDateAsync ( subscription ) ;
665667
666668 if ( suspensionDate . HasValue && unpaidPeriodEndDate . HasValue )
@@ -702,6 +704,74 @@ public async Task<SubscriptionInfo> GetSubscriptionAsync(ISubscriber subscriber)
702704 return subscriptionInfo ;
703705 }
704706
707+ private async Task ApplySchedulePhase2DataAsync ( Subscription subscription , SubscriptionInfo subscriptionInfo )
708+ {
709+ if ( string . IsNullOrEmpty ( subscription . ScheduleId ) )
710+ {
711+ return ;
712+ }
713+
714+ try
715+ {
716+ var schedule = await _stripeAdapter . GetSubscriptionScheduleAsync ( subscription . ScheduleId ,
717+ new SubscriptionScheduleGetOptions
718+ {
719+ Expand = [ "phases.discounts.coupon" , "phases.items.price" ]
720+ } ) ;
721+
722+ if ( schedule . Status != StripeConstants . SubscriptionScheduleStatus . Active || schedule . Phases . Count < 2 )
723+ {
724+ return ;
725+ }
726+
727+ var phase2 = schedule . Phases [ 1 ] ;
728+ var now = subscription . TestClock ? . FrozenTime ?? DateTime . UtcNow ;
729+
730+ if ( phase2 . StartDate < now )
731+ {
732+ return ;
733+ }
734+
735+ // Override line item amounts with Phase 2 prices
736+ if ( phase2 . Items != null && subscriptionInfo . Subscription ? . Items != null )
737+ {
738+ var items = subscriptionInfo . Subscription . Items . ToList ( ) ;
739+ foreach ( var phase2Item in phase2 . Items )
740+ {
741+ if ( phase2Item . Price is not { UnitAmount : not null , ProductId : not null } )
742+ {
743+ continue ;
744+ }
745+
746+ var matchingItem = items . FirstOrDefault ( i => i . ProductId == phase2Item . Price . ProductId ) ;
747+ if ( matchingItem != null )
748+ {
749+ matchingItem . Amount = phase2Item . Price . UnitAmount . Value / 100M ;
750+ }
751+ }
752+
753+ subscriptionInfo . Subscription . Items = items ;
754+ }
755+
756+ // Override discount with Phase 2 discount
757+ var phase2Discount = phase2 . Discounts ? . FirstOrDefault ( ) ;
758+ if ( phase2Discount ? . Coupon != null )
759+ {
760+ subscriptionInfo . CustomerDiscount = new SubscriptionInfo . BillingCustomerDiscount ( phase2Discount . Coupon ) ;
761+ }
762+ }
763+ catch ( StripeException ex )
764+ {
765+ // Fallback: user sees current Phase 1 prices instead of Phase 2 prices.
766+ // Accepted tradeoff: showing current data is better than failing the page.
767+ _logger . LogWarning ( ex ,
768+ "Failed to retrieve subscription schedule ({ScheduleId}) for subscription ({SubscriptionId}), Phase 2 data resolution. Error Code: {ErrorCode}" ,
769+ subscription . ScheduleId ,
770+ subscription . Id ,
771+ ex . StripeError ? . Code ) ;
772+ }
773+ }
774+
705775 public async Task < string > AddSecretsManagerToSubscription (
706776 Organization org ,
707777 StaticStore . Plan plan ,
0 commit comments