11/* eslint-disable @typescript-eslint/naming-convention */
2+ import { randomUUID } from 'crypto' ;
23import { inject } from '@loopback/core' ;
34import chargebee from 'chargebee' ;
45import {
5- CollectionMethod ,
66 RecurringInterval ,
77 TInvoicePrice ,
88 TPrice ,
@@ -353,8 +353,11 @@ export class ChargeBeeService implements IChargeBeeService {
353353 async createPrice ( price : TPrice ) : Promise < TPrice > {
354354 try {
355355 // Chargebee requires an explicit ItemPrice ID or auto-generates one.
356+ // randomUUID() is cryptographically secure (Node.js built-in v14.17+);
357+ // the first 8-hex segment keeps the ID short and Chargebee-friendly.
356358 const priceId =
357- price . id ?? `${ price . product } -${ price . currency } -${ Date . now ( ) } ` ;
359+ price . id ??
360+ `${ price . product } -${ price . currency } -${ randomUUID ( ) . split ( '-' ) [ 0 ] } ` ;
358361
359362 const result = await chargebee . item_price
360363 . create ( {
@@ -410,24 +413,10 @@ export class ChargeBeeService implements IChargeBeeService {
410413 */
411414 async createSubscription ( subscription : TSubscriptionCreate ) : Promise < string > {
412415 try {
416+ const params =
417+ this . chargebeeSubscriptionAdapter . adaptFromModel ( subscription ) ;
413418 const result = await chargebee . subscription
414- . create_with_items ( subscription . customerId , {
415- subscription_items : [
416- {
417- item_price_id : subscription . priceRefId ,
418- } ,
419- ] ,
420- discounts : [ ] , // Required by Chargebee SDK type
421- ...( subscription . collectionMethod === CollectionMethod . SEND_INVOICE
422- ? {
423- auto_collection : 'off' as const ,
424- // Only include net_term_days if explicitly provided and site has payment terms configured
425- ...( subscription . daysUntilDue !== undefined
426- ? { net_term_days : subscription . daysUntilDue }
427- : { } ) ,
428- }
429- : { auto_collection : 'on' as const } ) ,
430- } )
419+ . create_with_items ( subscription . customerId , params )
431420 . request ( ) ;
432421 return result . subscription . id ;
433422 } catch ( error ) {
@@ -579,11 +568,7 @@ export class ChargeBeeService implements IChargeBeeService {
579568 // Using collect_payment without a payment_source triggers Chargebee to
580569 // send the hosted payment page link to the customer by email
581570 // (based on site notification settings).
582- await chargebee . invoice
583- . collect_payment ( invoiceId , {
584- payment_source_id : undefined ,
585- } )
586- . request ( ) ;
571+ await chargebee . invoice . collect_payment ( invoiceId , { } ) . request ( ) ;
587572 } catch ( error ) {
588573 throw new Error ( JSON . stringify ( error ) ) ;
589574 }
@@ -600,15 +585,14 @@ export class ChargeBeeService implements IChargeBeeService {
600585 const result = await chargebee . item . retrieve ( productId ) . request ( ) ;
601586 return result . item . status === 'active' ;
602587 } catch ( error ) {
603- // Chargebee throws a JSON error string with api_error_code for not-found
604- const message = JSON . stringify ( error ) ;
588+ const cbError = error as { api_error_code ?: string ; http_status ?: number } ;
605589 if (
606- message . includes ( 'resource_not_found' ) ||
607- message . includes ( 'not_found' )
590+ cbError . api_error_code === 'resource_not_found' ||
591+ cbError . http_status === 404
608592 ) {
609593 return false ;
610594 }
611- throw new Error ( message ) ;
595+ throw new Error ( JSON . stringify ( error ) ) ;
612596 }
613597 }
614598}
0 commit comments