@@ -592,6 +592,11 @@ public async Task<IActionResult> BuyAddon(string planAddonId)
592592 {
593593 var model = new BuyAddonView ( ) ;
594594 model . PlanAddon = await _subscriptionsService . GetPlanAddonByIdAsync ( planAddonId ) ;
595+ // GetPlanAddonByIdAsync returns null when the add-on id isn't found (or the Billing API is
596+ // unavailable). Bail before dereferencing model.PlanAddon below (PlanAddonId / AddonType / PlanId).
597+ if ( model . PlanAddon == null )
598+ return NotFound ( ) ;
599+
595600 model . PlanAddonId = model . PlanAddon . PlanAddonId ;
596601 model . Department = await _departmentsService . GetDepartmentByIdAsync ( DepartmentId ) ;
597602 var addonTypes = await _subscriptionsService . GetAllAddonPlansAsync ( ) ;
@@ -620,6 +625,12 @@ public async Task<IActionResult> ManagePTTAddon()
620625 {
621626 var model = new BuyAddonView ( ) ;
622627 model . PlanAddon = await _subscriptionsService . GetPlanAddonByIdAsync ( "6f4c5f8b-584d-4291-8a7d-29bf97ae6aa9" ) ;
628+ // GetPlanAddonByIdAsync returns null when the Billing API is unavailable / the add-on isn't found.
629+ // The id here is hardcoded (a known product), so a null means a server/billing problem, not a bad
630+ // request — surface a 500 instead of NRE'ing on model.PlanAddon below.
631+ if ( model . PlanAddon == null )
632+ return StatusCode ( StatusCodes . Status500InternalServerError , "Unable to load the PTT add-on. Please try again." ) ;
633+
623634 model . PlanAddonId = model . PlanAddon . PlanAddonId ;
624635 model . Department = await _departmentsService . GetDepartmentByIdAsync ( DepartmentId ) ;
625636
@@ -775,6 +786,11 @@ public async Task<IActionResult> GetStripeSession(int id, int count, string disc
775786 var department = await _departmentsService . GetDepartmentByIdAsync ( DepartmentId ) ;
776787 var user = _usersService . GetUserById ( UserId ) ;
777788 var session = await _subscriptionsService . CreateStripeSessionForSub ( DepartmentId , stripeCustomerId , plan . GetExternalKey ( ) , plan . PlanId , user . Email , department . Name , count , discountCode ) ;
789+ // CreateStripeSessionForSub returns null when the Billing API is unavailable / Stripe session
790+ // creation fails. Fail with a clear error instead of NRE'ing on session.CustomerId/SessionId below.
791+ if ( session == null )
792+ return StatusCode ( StatusCodes . Status500InternalServerError , "Unable to start the checkout session. Please try again." ) ;
793+
778794 var subscription = await _subscriptionsService . GetActiveStripeSubscriptionAsync ( session . CustomerId ) ;
779795
780796 bool hasActiveSub = false ;
0 commit comments